typelevel-ts
Advanced tools
+5
-0
@@ -16,2 +16,7 @@ # Changelog | ||
| # 0.3.0 | ||
| - **Breaking Change** | ||
| - upgrade to `typescript@2.9.x` (@gcanti) | ||
| # 0.2.4 | ||
@@ -18,0 +23,0 @@ |
+22
-202
@@ -1,205 +0,25 @@ | ||
| export declare type Increment = { | ||
| 0: '1'; | ||
| 1: '2'; | ||
| 2: '3'; | ||
| 3: '4'; | ||
| 4: '5'; | ||
| 5: '6'; | ||
| 6: '7'; | ||
| 7: '8'; | ||
| 8: '9'; | ||
| 9: '10'; | ||
| 10: never; | ||
| /** | ||
| * Returns the string literal 'T' if `A` and `B` are equal types, 'F' otherwise | ||
| */ | ||
| export declare type Equals<A, B> = [A] extends [B] ? ([B] extends [A] ? 'T' : 'F') : 'F'; | ||
| /** | ||
| * Extracts a super-type of `A` identified by its keys `K` | ||
| */ | ||
| export declare type Omit<A extends object, K extends string | number | symbol> = Pick<A, Exclude<keyof A, K>>; | ||
| export declare type Overwrite<A extends object, B extends object> = Pick<A, Exclude<keyof A, keyof B>> & B; | ||
| export declare type Diff<A extends object, K extends keyof A> = Omit<A, K> & Partial<Pick<A, K>>; | ||
| /** | ||
| * Encodes the constraint that a given object `A` | ||
| * does not contain specific keys `K` | ||
| */ | ||
| export declare type RowLacks<A extends object, K extends string | number | symbol> = A & Record<Extract<keyof A, K>, never>; | ||
| export declare type Exact<A extends object, B extends A> = A & Record<Exclude<keyof B, keyof A>, undefined>; | ||
| export declare type AnyTuple = Array<any> & { | ||
| '0': any; | ||
| }; | ||
| export declare type StringToNumber = { | ||
| 0: 0; | ||
| 1: 1; | ||
| 2: 2; | ||
| 3: 3; | ||
| 4: 4; | ||
| 5: 5; | ||
| 6: 6; | ||
| 7: 7; | ||
| 8: 8; | ||
| 9: 9; | ||
| 10: 10; | ||
| }; | ||
| export declare type Bool = 'T' | 'F'; | ||
| export declare type If<B extends Bool, Then, Else> = { | ||
| T: Then; | ||
| F: Else; | ||
| }[B]; | ||
| export declare type Not<B extends Bool> = If<B, 'F', 'T'>; | ||
| export declare type And<B1 extends Bool, B2 extends Bool> = If<B1, B2, 'F'>; | ||
| export declare type Or<B1 extends Bool, B2 extends Bool> = If<B1, 'T', B2>; | ||
| export declare type BoolEq<B1 extends Bool, B2 extends Bool> = If<B1, B2, Not<B2>>; | ||
| export declare type Option<A> = None | Some<A>; | ||
| export interface None { | ||
| isNone: 'T'; | ||
| _A: never; | ||
| export interface DeepReadonlyArray<A> extends ReadonlyArray<DeepReadonly<A>> { | ||
| } | ||
| export interface Some<A> { | ||
| isNone: 'F'; | ||
| _A: A; | ||
| } | ||
| export declare type IsNone<O extends Option<any>> = O['isNone']; | ||
| export declare type IsSome<O extends Option<any>> = Not<IsNone<O>>; | ||
| export declare type OptionUnsafeGet<O extends Option<any>> = O['_A']; | ||
| export declare type OptionGetOrElse<O extends Option<any>, A> = If<IsNone<O>, A, OptionUnsafeGet<O>>; | ||
| export interface Zero { | ||
| isZero: 'T'; | ||
| prev: never; | ||
| } | ||
| export interface Succ<N extends Nat> { | ||
| isZero: 'F'; | ||
| prev: N; | ||
| } | ||
| export declare type Nat = Zero | Succ<any>; | ||
| export declare type One = Succ<Zero>; | ||
| export declare type Two = Succ<One>; | ||
| export declare type Three = Succ<Two>; | ||
| export declare type Four = Succ<Three>; | ||
| export declare type Five = Succ<Four>; | ||
| export declare type Six = Succ<Five>; | ||
| export declare type Seven = Succ<Six>; | ||
| export declare type Eight = Succ<Seven>; | ||
| export declare type Nine = Succ<Eight>; | ||
| export declare type Ten = Succ<Nine>; | ||
| export declare type IsZero<N extends Nat> = N['isZero']; | ||
| export declare type Prev<N extends Nat> = N['prev']; | ||
| export declare type NatEq<N1 extends Nat, N2 extends Nat> = { | ||
| T: IsZero<N2>; | ||
| F: If<IsZero<N2>, 'F', NatEq<Prev<N1>, Prev<N2>>>; | ||
| }[IsZero<N1>]; | ||
| export declare type Add<N1 extends Nat, N2 extends Nat> = { | ||
| T: N2; | ||
| F: Succ<Add<Prev<N1>, N2>>; | ||
| }[IsZero<N1>]; | ||
| export declare type Sub<N1 extends Nat, N2 extends Nat> = { | ||
| T: If<IsZero<N2>, Some<Zero>, None>; | ||
| F: If<IsZero<N2>, Some<N1>, Sub<Prev<N1>, Prev<N2>>>; | ||
| }[IsZero<N1>]; | ||
| export declare type UnsafeSub<N1 extends Nat, N2 extends Nat> = OptionGetOrElse<Sub<N1, N2>, Zero>; | ||
| export declare type Mult<N1 extends Nat, N2 extends Nat> = { | ||
| T: Zero; | ||
| F: If<IsZero<Prev<N1>>, N2, Add<N2, Mult<Prev<N1>, N2>>>; | ||
| }[IsZero<N1>]; | ||
| export declare type Lte<N1 extends Nat, N2 extends Nat> = { | ||
| T: 'T'; | ||
| F: If<IsZero<N2>, 'F', Lte<Prev<N1>, Prev<N2>>>; | ||
| }[IsZero<N1>]; | ||
| export declare type Lt<N1 extends Nat, N2 extends Nat> = And<Lte<N1, N2>, Not<NatEq<N1, N2>>>; | ||
| export declare type Gte<N1 extends Nat, N2 extends Nat> = Not<Lt<N1, N2>>; | ||
| export declare type Gt<N1 extends Nat, N2 extends Nat> = Not<Lte<N1, N2>>; | ||
| export declare type Mod<N1 extends Nat, N2 extends Nat, R = Zero> = { | ||
| T: R; | ||
| F: Mod<N1, N2, UnsafeSub<N1, N2>>; | ||
| }[IsZero<N1>]; | ||
| export declare type Min<N1 extends Nat, N2 extends Nat> = If<Lte<N1, N2>, N1, N2>; | ||
| export declare type Max<N1 extends Nat, N2 extends Nat> = If<Lte<N1, N2>, N2, N1>; | ||
| export declare type NatToString<N extends Nat, I extends keyof Increment = '0'> = { | ||
| T: I; | ||
| F: NatToString<Prev<N>, Increment[I]>; | ||
| }[IsZero<N>]; | ||
| export declare type NatToNumber<N extends Nat> = StringToNumber[NatToString<N>]; | ||
| export declare type StringToNat = { | ||
| 0: Zero; | ||
| 1: One; | ||
| 2: Two; | ||
| 3: Three; | ||
| 4: Four; | ||
| 5: Five; | ||
| 6: Six; | ||
| 7: Seven; | ||
| 8: Eight; | ||
| 9: Nine; | ||
| 10: Ten; | ||
| export declare type DeepReadonlyObject<A> = { | ||
| readonly [K in keyof A]: DeepReadonly<A[K]>; | ||
| }; | ||
| export declare type StringOmit<L1 extends string, L2 extends string> = ({ | ||
| [P in L1]: P; | ||
| } & { | ||
| [P in L2]: never; | ||
| } & { | ||
| [key: string]: never; | ||
| })[L1]; | ||
| export declare type StringEq<L1 extends string, L2 extends string> = And<StringContains<L1, L2>, StringContains<L2, L1>>; | ||
| export declare type StringIntersection<L1 extends string, L2 extends string> = StringOmit<L1, StringOmit<L1, L2>>; | ||
| export declare type StringContains<S extends string, L extends string> = ({ | ||
| [K in S]: 'T'; | ||
| } & { | ||
| [key: string]: 'F'; | ||
| })[L]; | ||
| export declare type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>; | ||
| export declare type ObjectOverwrite<O1, O2> = Pick<O1, StringOmit<keyof O1, keyof O2>> & O2; | ||
| export declare type ObjectOmit<O, K extends string> = Pick<O, StringOmit<keyof O, K>>; | ||
| export declare type ObjectDiff<O1 extends O2, O2> = ObjectOmit<O1, keyof O2> & Partial<O2>; | ||
| export declare type ObjectClean<T> = Pick<T, keyof T>; | ||
| export declare type ObjectOptional<O, K extends keyof O> = ObjectOmit<O, K> & Partial<Pick<O, K>>; | ||
| export declare type PickExact<O, K extends keyof O> = Pick<O, K> & { | ||
| [K1 in StringOmit<keyof O, K>]?: never; | ||
| }; | ||
| export declare type Required<T> = { | ||
| [P in Purify<keyof T>]: NonNullable<T[P]>; | ||
| }; | ||
| export declare type Purify<T extends string> = { | ||
| [P in T]: T; | ||
| }[T]; | ||
| export declare type NonNullable<T> = T & {}; | ||
| export interface HNil { | ||
| isHNil: 'T'; | ||
| head: never; | ||
| tail: never; | ||
| } | ||
| export interface HCons<H, T extends HList> { | ||
| isHNil: 'F'; | ||
| head: H; | ||
| tail: T; | ||
| } | ||
| export declare type HList = HNil | HCons<any, any>; | ||
| export declare type IsHNil<L extends HList> = L['isHNil']; | ||
| export declare type Head<L extends HList> = L['head']; | ||
| export declare type Tail<L extends HList> = L['tail']; | ||
| export declare type TypeAt<L extends HList, I extends Nat> = { | ||
| T: None; | ||
| F: If<IsZero<I>, Some<Head<L>>, TypeAt<Tail<L>, Prev<I>>>; | ||
| }[IsHNil<L>]; | ||
| export declare type UnsafeTypeAt<L extends HList, N extends Nat> = OptionGetOrElse<TypeAt<L, N>, never>; | ||
| export declare type Reverse<L extends HList, Acc extends HList = HNil> = { | ||
| T: Acc; | ||
| F: Reverse<Tail<L>, HCons<Head<L>, Acc>>; | ||
| }[IsHNil<L>]; | ||
| export declare type HListLengthAsNat<L extends HList> = { | ||
| T: Zero; | ||
| F: Succ<HListLengthAsNat<Tail<L>>>; | ||
| }[IsHNil<L>]; | ||
| export declare type HListLengthAsString<L extends HList> = { | ||
| T: '0'; | ||
| F: Increment[HListLengthAsString<Tail<L>>]; | ||
| }[IsHNil<L>]; | ||
| export declare type HListLengthAsNumber<L extends HList> = StringToNumber[HListLengthAsString<L>]; | ||
| export declare type HListToTuple<L extends HList> = { | ||
| 0: never; | ||
| 1: [Head<L>]; | ||
| 2: [Head<L>, Head<Tail<L>>]; | ||
| 3: [Head<L>, Head<Tail<L>>, Head<Tail<Tail<L>>>]; | ||
| 4: [Head<L>, Head<Tail<L>>, Head<Tail<Tail<L>>>, Head<Tail<Tail<Tail<L>>>>]; | ||
| 5: [Head<L>, Head<Tail<L>>, Head<Tail<Tail<L>>>, Head<Tail<Tail<Tail<L>>>>, Head<Tail<Tail<Tail<Tail<L>>>>>]; | ||
| 6: [Head<L>, Head<Tail<L>>, Head<Tail<Tail<L>>>, Head<Tail<Tail<Tail<L>>>>, Head<Tail<Tail<Tail<Tail<L>>>>>, Head<Tail<Tail<Tail<Tail<Tail<L>>>>>>]; | ||
| }[HListLengthAsString<L>]; | ||
| export declare type HListConcat<L1 extends HList, L2 extends HList> = { | ||
| T: L2; | ||
| F: HCons<Head<L1>, HListConcat<Tail<L1>, L2>>; | ||
| }[IsHNil<L1>]; | ||
| export declare type AnyTuple = Array<any> & { | ||
| '0': any; | ||
| }; | ||
| export declare type TupleToObject<T> = ObjectOmit<T, keyof Array<any>>; | ||
| export declare type TupleLengthAsString<T extends AnyTuple, I extends keyof Increment = '0'> = { | ||
| T: TupleLengthAsString<T, Increment[I]>; | ||
| F: I; | ||
| }[ObjectHasKey<T, I>]; | ||
| export declare type TupleLengthAsNumber<T extends AnyTuple> = StringToNumber[TupleLengthAsString<T>]; | ||
| export declare type TupleToHList<T extends AnyTuple, I extends keyof Increment & keyof T = '0', L extends HList = HNil> = { | ||
| T: TupleToHList<T, Increment[I], HCons<T[I], L>>; | ||
| F: Reverse<L>; | ||
| }[ObjectHasKey<T, I>]; | ||
| export declare type DeepReadonly<A> = A extends Array<infer B> ? DeepReadonlyArray<B> : DeepReadonlyObject<A>; |
+0
-3
| "use strict"; | ||
| // | ||
| // helpers | ||
| // | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| //# sourceMappingURL=index.js.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,EAAE;AACF,UAAU;AACV,EAAE"} | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""} |
+8
-6
| { | ||
| "name": "typelevel-ts", | ||
| "version": "0.2.4", | ||
| "version": "0.3.0", | ||
| "description": "Type level programming in TypeScript", | ||
@@ -12,8 +12,8 @@ "files": [ | ||
| "lint": "tslint src/**/*.ts", | ||
| "typings-checker": "typings-checker --allow-expect-error --project typings-checker/tsconfig.json typings-checker/index.ts", | ||
| "prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,typings-checker}/**/*.ts\"", | ||
| "fix-prettier": "prettier --no-semi --single-quote --print-width 120 --parser typescript --write \"{src,typings-checker}/**/*.ts\"", | ||
| "test": "npm run prettier && npm run lint && npm run typings-checker", | ||
| "test": "npm run prettier && npm run lint && npm run dtslint", | ||
| "clean": "rm -rf lib/*", | ||
| "build": "npm run clean && tsc" | ||
| "build": "npm run clean && tsc", | ||
| "dtslint": "dtslint dtslint" | ||
| }, | ||
@@ -32,7 +32,9 @@ "repository": { | ||
| "devDependencies": { | ||
| "@types/react": "^16.3.17", | ||
| "dtslint": "^0.3.0", | ||
| "prettier": "^1.13.4", | ||
| "react": "^16.4.0", | ||
| "tslint": "4.4.2", | ||
| "tslint-config-standard": "4.0.0", | ||
| "typescript": "2.8.3", | ||
| "typings-checker": "^2.0.0" | ||
| "typescript": "^2.9.2" | ||
| }, | ||
@@ -39,0 +41,0 @@ "tags": [], |
+57
-76
@@ -1,105 +0,86 @@ | ||
| # Compatibility | ||
| # TypeScript compatibility | ||
| * `0.2.0+` for TypeScript `2.5.2+` | ||
| * `0.1.3` for TypeScript `2.4.1+` | ||
| The stable version is tested against TypeScript 2.9.1+ | ||
| # Credits | ||
| # API | ||
| Adapted from | ||
| ## Equals<A, B> | ||
| * https://github.com/Microsoft/TypeScript/issues/14833 | ||
| * https://github.com/Microsoft/TypeScript/issues/16392 | ||
| * https://github.com/Microsoft/TypeScript/issues/12215 | ||
| Returns the string literal 'T' if `A` and `B` are equal types, 'F' otherwise | ||
| ## Related projects | ||
| ```ts | ||
| Equals<string, string> // "T" | ||
| Equals<string, number> // "F" | ||
| ``` | ||
| * [typical - playground for type-level primitives in TypeScript](https://github.com/tycho01/typical) by @tycho01 | ||
| ## Omit<A extends object, K extends string | number | symbol> | ||
| # Examples | ||
| Extracts a super-type of `A` identified by its keys `K` | ||
| ## Naturals | ||
| ```ts | ||
| Omit<{ a: string; b: number }, 'a'> // { b: number } | ||
| ``` | ||
| **Example**. Type-safe vectors | ||
| ## Overwrite<A extends object, B extends object> | ||
| ```ts | ||
| import { One, Two, Three, Nat, Add } from 'typelevel-ts' | ||
| Overwrite<{ a: string; b: number }, { b: boolean }> // { a: string; b: boolean } | ||
| ``` | ||
| function create<A>(as: [A, A, A]): Vector<Three, A> | ||
| function create<A>(as: [A, A]): Vector<Two, A> | ||
| function create<A>(as: [A]): Vector<One, A> | ||
| function create<N extends Nat, A>(as: Array<A>): Vector<N, A> { | ||
| return new Vector<N, A>(as) | ||
| } | ||
| ## Diff<A extends object, K extends keyof A> | ||
| class Vector<N extends Nat, A> { | ||
| static create = create | ||
| readonly _N: N | ||
| readonly _A: A | ||
| constructor(public value: Array<A>) {} | ||
| append<N2 extends Nat>(vector: Vector<N2, A>): Vector<Add<N, N2>, A> { | ||
| return new Vector<Add<N, N2>, A>(this.value.concat(vector.value)) | ||
| } | ||
| zip<B>(vector: Vector<N, B>): Vector<N, [A, B]> { | ||
| return new Vector<N, [A, B]>(this.value.map((a, i) => [a, vector.value[i]] as [A, B])) | ||
| } | ||
| inspect() { | ||
| return this.toString() | ||
| } | ||
| toString() { | ||
| return `Vector(${JSON.stringify(this.value)})` | ||
| } | ||
| } | ||
| ```ts | ||
| Diff<{ a: string; b: number }, 'b'> // { a: string; b?: number } | ||
| ``` | ||
| // v1 :: Vector<One, number> | ||
| const v1 = Vector.create([1]) | ||
| // v2 :: Vector<Two, number> | ||
| const v2 = Vector.create([2, 3]) | ||
| // v3 :: Vector<Three, number> | ||
| const v3 = v1.append(v2) | ||
| ## RowLacks<A extends object, K extends string | number | symbol> | ||
| // v3.zip(v2) // error | ||
| Encodes the constraint that a given object `A` does not contain specific keys `K` | ||
| console.log(v2.zip(v1.append(v1))) // Vector([[2,1],[3,1]]) | ||
| ```ts | ||
| declare function f(x: RowLacks<{ a: string; b: number }, 'a'>): void | ||
| // $ExpectError | ||
| f({ a: 'foo', b: 1 }) | ||
| ``` | ||
| ## `ObjectDiff` | ||
| ## Exact<A extends object, B extends A> | ||
| **Example**. A `withDefaults` function (React) | ||
| ```ts | ||
| import * as React from 'react' | ||
| import { ObjectDiff } from 'typelevel-ts'; | ||
| import isUndefined from 'lodash/isUndefined'; | ||
| import omitBy from 'lodash/omitBy'; | ||
| declare function f<T extends Exact<{ a: string }, T>>(a: T): void | ||
| declare const x: { a: string } | ||
| declare const y: { a: string; b: number } | ||
| f(x) | ||
| // $ExpectError | ||
| f(y) | ||
| ``` | ||
| function withDefaults<D, A extends D>(C: React.ComponentType<A>, defaults: D): React.SFC<ObjectDiff<A, D>> { | ||
| return props => { | ||
| // If a prop is provided with a value of `undefined`, we want the default prop to take | ||
| // precendence. This ensures the behaviour matches that of React's built-in `defaultProps` | ||
| // static property on components. | ||
| const propsMinusUndefined = omitBy(props, isUndefined); | ||
| return <C {...defaults} {...propsMinusUndefined} />; | ||
| }; | ||
| }; | ||
| ## AnyTuple | ||
| class Foo extends React.Component<{ bar: string; baz: number }> {} | ||
| const DefaultedFoo = withDefaults(Foo, { baz: 1 }) | ||
| const x = <DefaultedFoo bar="bar" /> // ok | ||
| ```ts | ||
| declare function f<T extends AnyTuple>(x: T): T | ||
| declare const x: [number] | ||
| declare const y: [number, string] | ||
| declare const z: [number, string, boolean] | ||
| declare const t: Array<number> | ||
| f(x) | ||
| f(y) | ||
| f(z) | ||
| // $ExpectError | ||
| f(t) | ||
| ``` | ||
| ## `ObjectOmit` | ||
| ## DeepReadonly<A> | ||
| **Example**. A `withProps` function (React) | ||
| ```ts | ||
| import { ObjectOmit } from 'typelevel-ts' | ||
| import * as React from 'react' | ||
| function withProps<D, P extends D>(C: React.ComponentType<P>, values: D): React.SFC<ObjectOmit<P, keyof D>> { | ||
| return props => <C {...props} {...values} /> | ||
| interface Foo { | ||
| bar: { | ||
| baz: string | ||
| quux: Array<{ barbaz: number }> | ||
| } | ||
| } | ||
| class Foo extends React.Component<{ bar: string; baz: number }> {} | ||
| const FilledFoo = withProps(Foo, { baz: 1 }) | ||
| const x = <FilledFoo bar="bar" /> // ok | ||
| type ReadonlyFoo = DeepReadonly<Foo> | ||
| declare const x: ReadonlyFoo | ||
| // $ExpectError | ||
| x.bar.quux[1].barbaz = 1 | ||
| ``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
6538
-53.64%7
40%27
-87.14%87
-17.92%1
Infinity%