Coder Social home page Coder Social logo

mscharley / generic-type-guard Goto Github PK

View Code? Open in Web Editor NEW
50.0 4.0 3.0 3.76 MB

Type safe, composable type guards for TypeScript

Home Page: https://www.npmjs.com/package/generic-type-guard

License: MIT License

TypeScript 100.00%
type-guards type-safety typescript input-validation

generic-type-guard's Introduction

generic-type-guard

npm CircleCI

Source: https://github.com/mscharley/generic-type-guard
Author: Matthew Scharley
Contributors: See contributors on GitHub
Bugs/Support: Github Issues
Copyright: 2022
License: MIT license
Status: Active

Synopsis

This library is an attempt to manage creating type guards in a sensible way, making them composable and reusable.

Installation

$ npm i generic-type-guard

Usage

The point of this library is to provide a suite of type guard expressions that are themselves both type safe and composable in a type safe way. To that end we define two new types which are just aliases for the built-in type guard type:

export type PartialTypeGuard<T, U extends T> = (value: T) => value is U;
export type TypeGuard<T> = PartialTypeGuard<unknown, T>;

A PartialTypeGuard is a type guard which given a value of type T can prove it is actually the specialised type U. A TypeGuard is a type guard that can prove any value to be of type T; it is a PartialTypeGuard<unknown, T>.

Type safety

What do we mean by type safety when we're talking about something that in a lot of ways is inherantly type unsafe? We simply mean that if you change the definition your interface/variable/whatever you are checking then your type guard should no longer successfully compile. Most of the type safety comes from leveraging the compiler, therefore you must define your typeguards in the following way to make them the most effective:

interface Foo {
	foo: string;
	bar: number;
}

// this fails.
const isBrokenFoo: tg.TypeGuard<Foo> = tg.isRecord('foo', tg.isString);

// this works.
const isFoo: tg.TypeGuard<Foo> = new tg.IsInterface()
	.withProperty('foo', tg.isString)
	.withProperty('bar', tg.isNumber)
	.get();

// This works around the gotchas explained below but has other issues, especially with complex types.
// All guarantees are void if you use this format.
const isFoo = new tg.IsInterface().withProperty('foo', tg.isString).withProperty('bar', tg.isNumber).get();

It is highly recommended to assign an explicit type to the type guards you create to let the compiler ensure that you've caught everything.

Examples

Some examples:

import * as tg from 'generic-type-guard';

export const isComplexInterface = new tg.IsInterface()
	.withProperties({
		str: tg.isString,
		num: tg.isNumber,
		b: tg.isBoolean,
		maybeString: tg.isOptional(tg.isString),
		nullableString: tg.isNullable(tg.isString),
	})
	.get();
export type ComplexInterface = tg.GuardedType<typeof isComplexInterface>;

There are more detailed examples available.

Gotchas

TypeScript structural typing

generic-type-guard works with the TypeScript type system. You are guaranteed that the type guards you write are sufficient to prove that the thing provided to it conforms in one way or another to the type that the type guard checks for. But that doesn't necessarily mean that all valid values of that type will be allowed. Put another way, you are guaranteed to never get a false positive but you may get false negatives. In particular, union types can be troublesome.

An example helps illustrate this:

import * as tg from 'generic-type-guard';

type FooBar = 'foo' | 'bar';

const isFooBar: tg.TypeGuard<FooBar> = tg.isSingletonString('foo');

The above example checks for a single value "foo". This is a FooBar and so the type system does not complain. But if you try to pass "bar" into this type guard then it will return false.

Perhaps more insidiously:

interface Foo {
	foo?: string;
}

const isFoo: tg.TypeGuard<Foo> = tg.isRecord('foo', tg.isString);

Again, checking that foo is a string is sufficient to prove that it is either a string or undefined.

Fix for structural typing issues

If possible, you should reframe the question. Instead of creating a type to guard against, create a guard and export the type:

const isFoo = tg.isRecord('foo', tg.isOptional(tg.isString));
type Foo = tg.GuardedType<typeof isFoo>;

generic-type-guard's People

Contributors

dependabot[bot] avatar domparfitt avatar github-actions[bot] avatar gitter-badger avatar greenkeeper[bot] avatar greenkeeperio-bot avatar mscharley avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

generic-type-guard's Issues

An in-range update of testdouble is breaking the build 🚨

The devDependency testdouble was updated from 3.9.0 to 3.9.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

testdouble is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: carbon: Your tests failed on CircleCI (Details).

Commits

The new version differs by 5 commits.

  • 0a3670b Changelog for 3.9.1
  • 2f60d9e 3.9.1
  • 2c1e994 Merge pull request #396 from lisamai/lh/update-typescript-types
  • 85c78b6 Set version for npm-run-all to at least 4.1.5 for patched version and minimize lockfile changes
  • 908f9c2 Add type information for imitation to the exported typings file

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

Migrate to Stryker 1.0

warning workspace-aggregator-e67f84b6-7367-4925-a5f6-24ad061d01ad > generic-type-guard-cli > [email protected]: Stryker v1 is released, but you're still using a 0.x version. This version is no longer maintained. Please use @stryker-mutator/core. See https://stryker-mutator.io/blog/2019-02-13/announcing-stryker-1-0 for the full migration guide.
warning workspace-aggregator-e67f84b6-7367-4925-a5f6-24ad061d01ad > generic-type-guard > [email protected]: Stryker v1 is released, but you're still using a 0.x version. This version is no longer maintained. Please use @stryker-mutator/core. See https://stryker-mutator.io/blog/2019-02-13/announcing-stryker-1-0 for the full migration guide.

https://stryker-mutator.io/blog/2019-02-13/announcing-stryker-1-0

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

  • chore(deps): update dependency chai to v5.1.1
  • chore(deps): update dependency typescript to v5.5.2

Pending Status Checks

These updates await pending status checks. To force their creation now, click the checkbox below.

  • chore(deps): update dependency @changesets/cli to v2.27.7
  • chore(deps): update dependency esbuild to v0.23.0

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/changesets.yml
  • mscharley/.github main
.github/workflows/ci.yml
  • mscharley/.github main
  • mscharley/.github main
.github/workflows/renovate-changesets.yml
  • mscharley/.github main
.github/workflows/stale.yml
  • mscharley/.github main
npm
package.json
  • @changesets/cli 2.27.6
  • @microsoft/api-extractor 7.47.0
  • @mscharley/eslint-config 3.1.4
  • @mscharley/prettier-config 3.0.5
  • @stryker-mutator/core 8.2.6
  • @stryker-mutator/mocha-runner 8.2.6
  • @stryker-mutator/typescript-checker 8.2.6
  • @types/chai 4.3.16
  • @types/mocha 10.0.6
  • @types/node 20.14.9
  • c8 10.1.2
  • chai 5.1.0
  • esbuild 0.21.5
  • mocha 10.4.0
  • nodemon 3.1.4
  • rimraf 5.0.7
  • source-map-support 0.5.21
  • testdouble 3.20.2
  • ts-node 10.9.2
  • typescript 5.4.5
  • node >= 16
nvm
.nvmrc
  • node 20.15.0

  • Check this box to trigger a request for Renovate to run again on this repository

An in-range update of lerna is breaking the build 🚨

The devDependency lerna was updated from 3.6.0 to 3.7.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

lerna is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: carbon: Your tests failed on CircleCI (Details).

Commits

The new version differs by 40 commits.

  • 89b53ff chore(release): publish v3.7.0
  • 6116680 fix(create): Pass options snapshot to pacote.manifest()
  • 11c583c refactor(npm-conf): remove redundant check, add istanbul comments
  • d58b741 fix(npm-conf): Port kevva/npm-conf/pull/12 (@zkochan)
  • 6a8aa83 fix(npm-conf): Update defaults & types to npm v6.5.0+
  • db4522b refactor(publish): Snapshot options passed to n-r-f/auth helper
  • ca4dd95 fix(publish): Short-circuit retries for npm username validation
  • 405b094 refactor(publish): introduce figgy-pudding to share fetch opts
  • 111053b refactor(publish): swap snapshot call of unpublished packages helper
  • 2713ab8 feat(dist-tag): Wrap options in figgy-pudding
  • b1c2a10 test(helpers): import equals() method from jasmine_utils to support nested asymmetric matchers
  • d0f0dbc fix(add): Snapshot opts passed to pacote.manifest()
  • d4ab6c4 fix(publish): Remove unused dependency
  • 2de7234 refactor(publish): Snapshot conf before passing as opts
  • d0c677f refactor(pack-directory): Use figgy-pudding to wrap options, snapshot conf in test

There are 40 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Check for no extra properties

It would be nice to be able to create a typeguard that is only true if the value being tested is an object that contains the exact set of properties specified, and no other extra properties.

Oddities thanks to floating point numbers

td.isNumber(NaN) === true

Oops. isNumber should check !isNaN. Also, we should add a few extra checks.

// Is what a human would intuit as a number.
tg.isNumber(NaN) === false
tg.isNumber(Infinity) === true
tg.isNumber(10) === true

// Is strictly a NaN value.
tg.isNaN(NaN) === true
tg.isNaN(Infinity) === false
tg.isNaN(10) === false

// Is a finite number, ie. discount Infinity.
tg.isFiniteNumber(NaN) === false
tg.isFiniteNumber(Infinity) === false
tg.isFiniteNumber(10) === true

// Is strictly a number according to the TypeScript type system.
tg.isFloat = td.isDouble
tg.isDouble(NaN) === true
tg.isDouble(Infinity) === true
tg.isDouble(10) === true

All the above tests would be a TypeGuard<number> which is the best that TypeScript can represent.

Oddities when mixing TypeGuards with PartialTypeGuards

The following appears to compile and run and hence do the wrong thing.

const isFoo: tg.PartialTypeGuard<string, "foo"> = (s: string): s is "foo" => s === "foo";
const isSomething: { foo: "foo"[] } = tg.isRecord("foo", tg.narrowArray(isFoo));

Cannot use PartialTypeGuard in hasProperties/hasOnlyProperties

const isSample = tg.hasOnlyProperties({
  okay: tg.isBoolean,
  failing: tg.hasOnlyProperties({
    notokay: tg.isBoolean
  })
});

Error occurs on the failing, preventing combination of

Type 'PartialTypeGuard<object, { notokay: boolean; }>' is not assignable to type 'TypeGuard<{ notokay: boolean; }>'.
  Types of parameters 'value' and 'value' are incompatible.
    Type 'unknown' is not assignable to type 'object'.ts(2322)

Is there an obvious way to combine nested types?

An in-range update of @stryker-mutator/core is breaking the build 🚨

The devDependency @stryker-mutator/core was updated from 1.1.0 to 1.1.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@stryker-mutator/core is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… ci/circleci: carbon: Your tests passed on CircleCI! (Details).
  • ❌ ci/circleci: boron: CircleCI is running your tests (Details).
  • ❌ ci/circleci: latest: CircleCI is running your tests (Details).
  • ❌ ci/circleci: stryker: Your tests failed on CircleCI (Details).

Commits

The new version differs by 16 commits.

  • a4a0639 v1.1.1
  • ca13148 build(travis): re-enable node as runtime (#1462)
  • 5ba8660 build(deps): update @babel/traverse requirement from ~7.3.4 to ~7.4.0 (#1459)
  • d60d20b build(deps-dev): update @babel/core requirement from ~7.3.3 to ~7.4.0 (#1460)
  • 2331847 fix(broadcast-reporter): log error detail (#1461)
  • 588f832 build(deps): update typed-rest-client requirement from ~1.1.2 to ~1.2.0 (#1453)
  • ba74e6f build(deps-dev): update @babel/preset-env requirement (#1454)
  • 73bf226 build(deps): update @babel/generator requirement from ~7.3.2 to ~7.4.0 (#1455)
  • bf142e6 build(deps-dev): update @babel/types requirement from ~7.3.0 to ~7.4.0 (#1456)
  • 13a1058 build(deps-dev): update tslint requirement from ~5.13.0 to ~5.14.0 (#1448)
  • 412573e test(wct): improve test stability (#1447)
  • 278d9db build(deps): update get-port requirement from ~4.1.0 to ~4.2.0 (#1436)
  • e6c727f build(deps): update decamelize requirement from ^2.0.0 to ^3.0.0 (#1439)
  • 320f0bf build(deps-dev): update jsdom requirement from ~13.2.0 to ~14.0.0 (#1443)
  • 14305f7 build(travis): pin node version to 11.10 (#1444)

There are 16 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of testdouble is breaking the build 🚨

The devDependency testdouble was updated from 3.9.2 to 3.9.3.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

testdouble is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… ci/circleci: carbon: Your tests passed on CircleCI! (Details).
  • ❌ ci/circleci: boron: CircleCI is running your tests (Details).
  • ❌ ci/circleci: latest: CircleCI is running your tests (Details).
  • ❌ ci/circleci: stryker: Your tests failed on CircleCI (Details).

Commits

The new version differs by 13 commits.

  • efa931b Changelog for 3.9.3
  • a4ddffd 3.9.3
  • d5e6ea3 Merge pull request #401 from lgandecki/typescriptUsageDocs
  • b3e23e6 removed the link to the removed part of the documentation
  • 0b040a1 shortened the documentation for typescript
  • fe35830 fixed typo
  • 8977124 fix typo
  • 4acece6 fix typo
  • 69b3780 changed the name of abstract class to avoid confusion
  • 25e3c53 only one option for classes after all..
  • f94f4b2 fix the error message
  • 98fdb01 improved language, added the DI thinking with an example
  • 83435fb docs and updated types

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of mocha is breaking the build 🚨

The devDependency mocha was updated from 6.0.2 to 6.1.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

mocha is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: carbon: Your tests failed on CircleCI (Details).

Release Notes for v6.1.0

6.1.0 / 2019-04-07

πŸ”’ Security Fixes

  • #3845: Update dependency "js-yaml" to v3.13.0 per npm security advisory (@plroebuck)

πŸŽ‰ Enhancements

  • #3766: Make reporter constructor support optional options parameter (@plroebuck)
  • #3760: Add support for config files with .jsonc extension (@sstephant)

πŸ“  Deprecations

These are soft-deprecated, and will emit a warning upon use. Support will be removed in (likely) the next major version of Mocha:

πŸ› Fixes

  • #3829: Use cwd-relative pathname to load config file (@plroebuck)
  • #3745: Fix async calls of this.skip() in "before each" hooks (@juergba)
  • #3669: Enable --allow-uncaught for uncaught exceptions thrown inside hooks (@givanse)

and some regressions:

πŸ“– Documentation

πŸ”© Other

  • #3830: Replace dependency "findup-sync" with "find-up" for faster startup (@cspotcode)
  • #3799: Update devDependencies to fix many npm vulnerabilities (@XhmikosR)
Commits

The new version differs by 28 commits.

  • f4fc95a Release v6.1.0
  • bd29dbd update CHANGELOG for v6.1.0 [ci skip]
  • aaf2b72 Use cwd-relative pathname to load config file (#3829)
  • b079d24 upgrade deps as per npm audit fix; closes #3854
  • e87c689 Deprecate this.skip() for "after all" hooks (#3719)
  • 81cfa90 Copy Suite property "root" when cloning; closes #3847 (#3848)
  • 8aa2fc4 Fix issue 3714, hide pound icon showing on hover header on docs page (#3850)
  • 586bf78 Update JS-YAML to address security issue (#3845)
  • d1024a3 Update doc examples "tests.html" (#3811)
  • 1d570e0 Delete "/docs/example/chai.js"
  • ade8b90 runner.js: "self.test" undefined in Browser (#3835)
  • 0098147 Replace findup-sync with find-up for faster startup (#3830)
  • d5ba121 Remove "package" flag from sample config file because it can only be passes as CLI arg (#3793)
  • a3089ad update package-lock
  • 75430ec Upgrade yargs-parser dependency to avoid loading 2 copies of yargs

There are 28 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Generate TypeScript code files

This could be using strings, though it would be great if we could generate AST's and use the compiler to verify the typings before writing it out.

An in-range update of @stryker-mutator/typescript is breaking the build 🚨

The devDependency @stryker-mutator/typescript was updated from 1.1.0 to 1.1.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@stryker-mutator/typescript is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… ci/circleci: carbon: Your tests passed on CircleCI! (Details).
  • βœ… ci/circleci: latest: Your tests passed on CircleCI! (Details).
  • βœ… ci/circleci: boron: Your tests passed on CircleCI! (Details).
  • ❌ ci/circleci: stryker: Your tests failed on CircleCI (Details).

Commits

The new version differs by 16 commits.

  • a4a0639 v1.1.1
  • ca13148 build(travis): re-enable node as runtime (#1462)
  • 5ba8660 build(deps): update @babel/traverse requirement from ~7.3.4 to ~7.4.0 (#1459)
  • d60d20b build(deps-dev): update @babel/core requirement from ~7.3.3 to ~7.4.0 (#1460)
  • 2331847 fix(broadcast-reporter): log error detail (#1461)
  • 588f832 build(deps): update typed-rest-client requirement from ~1.1.2 to ~1.2.0 (#1453)
  • ba74e6f build(deps-dev): update @babel/preset-env requirement (#1454)
  • 73bf226 build(deps): update @babel/generator requirement from ~7.3.2 to ~7.4.0 (#1455)
  • bf142e6 build(deps-dev): update @babel/types requirement from ~7.3.0 to ~7.4.0 (#1456)
  • 13a1058 build(deps-dev): update tslint requirement from ~5.13.0 to ~5.14.0 (#1448)
  • 412573e test(wct): improve test stability (#1447)
  • 278d9db build(deps): update get-port requirement from ~4.1.0 to ~4.2.0 (#1436)
  • e6c727f build(deps): update decamelize requirement from ^2.0.0 to ^3.0.0 (#1439)
  • 320f0bf build(deps-dev): update jsdom requirement from ~13.2.0 to ~14.0.0 (#1443)
  • 14305f7 build(travis): pin node version to 11.10 (#1444)

There are 16 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of reflect-metadata is breaking the build 🚨

The dependency reflect-metadata was updated from 0.1.12 to 0.1.13.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

reflect-metadata is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • βœ… ci/circleci: carbon: Your tests passed on CircleCI! (Details).
  • ❌ ci/circleci: latest: Your tests failed on CircleCI (Details).
  • ❌ ci/circleci: stryker: Your tests failed on CircleCI (Details).
  • βœ… ci/circleci: boron: Your tests passed on CircleCI! (Details).

Commits

The new version differs by 3 commits.

  • aacaeb1 0.1.13
  • 5b98fe1 Do not generate source maps when publishing
  • c2dbe1d Add test to verify does not overwrite existing implementation

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of nodemon is breaking the build 🚨

The devDependency nodemon was updated from 1.18.5 to 1.18.6.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

nodemon is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ ci/circleci: carbon: Your tests failed on CircleCI (Details).

Release Notes for v1.18.6

1.18.6 (2018-11-05)

Bug Fixes

Commits

The new version differs by 1 commits.

  • 521eb1e fix: restart on change for non-default signals (#1409) (#1430)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

global is not defined in browser

When using generic-type-guard in a browser environment, I receive the following error:

global is not defined

Current workaround

I currently work around this issue by defining window.global somewhere before running generic-type-guard e.g. in a script tag.

<script>window.global = window;</script>

Proposed solution

generic-type-guard could add native support for browsers by using globalThis instead of global.

There is a tiny catch though: globalThis is supported since Node 12. So Node 10 could no longer be supported, which shouldn't be a problem since it is EOL anyway (https://nodejs.org/en/about/releases/).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.