typelevel-ts
Advanced tools
Comparing version 0.2.4 to 0.3.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 @@ |
@@ -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>; |
"use strict"; | ||
// | ||
// helpers | ||
// | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"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": [], |
133
README.md
@@ -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 | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6538
7
27
87
1