Created
June 6, 2017 21:13
-
-
Save gcnew/ad833bfa376e4b70fc50a780e3b2d883 to your computer and use it in GitHub Desktop.
The test cases I'm using to verify my implementation of https://github.com/Microsoft/TypeScript/issues/9949
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export {} | |
interface Collection<T> { | |
length: number; | |
add(x: T): void; | |
remove(x: T): boolean; | |
} | |
interface Combinators { | |
map<T, U>(c: Collection<T>, f: (x: T) => U): Collection<U>; | |
map<T>(c: Collection<T>, f: (x: T) => any): Collection<any>; | |
forEach<T>(c: Collection<T>, f: (x: T) => Date): void; | |
} | |
declare var _: Combinators; | |
declare var c2: Collection<number>; | |
var rf1 = (x: number) => { return x.toFixed() }; | |
var r1a = _.map(c2, (x) => { return x.toFixed() }); | |
var r5 = _.forEach<number>(c2, rf1); // Should error | |
var r6 = _.forEach<number>(c2, (x) => { return x.toFixed() }); // Should error | |
declare const zipWith: <T, S, U>(a: T[], b: S[], f: (x: T) => (y: S) => U) => U[]; | |
declare const pair: <T, S>(x: T) => (y: S) => { x: T; y: S; } | |
const zr = zipWith([1, 2], ['a', 'b'], pair); | |
declare function lego1<A, B>(x: A, l: List<B>, y: A): A; | |
declare function lego2<C, D>(f: (l: List<C>, x: D, y: D) => D): void; | |
lego2(lego1); | |
declare function bombastic<R>(f: (x: string, y: number) => R): R; | |
declare function bombastic2(f: (x: string, y: number) => string): void; | |
declare function bombastic3<R>(f: (x: string, y: number, z: R) => R): R; | |
declare function okay<R>(f: (x: 1, y: number) => R): R; | |
declare function transitive<T>(x: T, f: (x: T) => T): void; | |
bombastic(id2); // Should be an error T = [string, number] | |
bombastic2(id2); // Should be an error T = [string, number] | |
bombastic<string|number>(id2); // Should be OK | |
declare function id3<T>(x: T, y: T, z: T): T; | |
bombastic3<string|number>(id3); // Should be OK | |
okay(id2); | |
transitive(1, withNum); | |
transitive('1', withNum); | |
declare function occurs<R>(f: (x: number, xs: List<number>) => R): R; | |
occurs(id2); | |
declare function f15<T extends number>(x: T, f: (x: T) => T): void; | |
declare function g15(n: number): number; | |
f15(5, g15); | |
interface J<T> { | |
[s: string]: T; | |
} | |
declare function g1<T>(obj: J<T>): T; | |
const rg1: string = g1({ p: "" }); | |
declare function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined; | |
class Node { | |
_node: any; | |
forEachChild<C>(cbNode: (node: Node) => C, cbNodeArray?: (nodes: NodeArray<Node>) => C): C { | |
return forEachChild(this, cbNode, cbNodeArray); | |
} | |
} | |
interface NodeBrand { _nodearray: any } | |
class Declaration extends Node { _declarationBrand: any; } | |
class ParameterDeclaration extends Declaration { _paramdecl: any; } | |
interface Arr<T> { | |
concat(...items: T[][]): T[]; | |
concat(...items: (T | T[])[]): T[]; | |
} | |
interface NodeArray<T extends Node> extends Arr<T>, NodeBrand { } | |
declare function indexOf<T>(hay: Arr<T>, needle: T): number; | |
declare const fps: NodeArray<ParameterDeclaration>; | |
declare const node: Node; | |
indexOf(fps, node); | |
function selfRef<T>(n: number, callback: (n: number) => T): T { | |
return selfRef(n, callback); | |
} | |
class A { x: any; } | |
class B extends A { y: any; } | |
class Chain<T extends A> { | |
then<S extends T>(cb: (x: T) => S): Chain<S> { | |
return null!; | |
} | |
} | |
declare const chainB: Chain<B>; | |
chainB.then(b => new A); | |
declare function f16(f: (x: number) => 4): void; | |
declare function g16(x: number): number; | |
f16(g16); | |
declare function trans<T>(f: (x: T) => string): number; | |
// TODO: these should all be noImplicitAny / destructuring erros | |
trans(({a}) => a); | |
trans(([b,c]) => 'foo'); | |
trans(({d: [e,f]}) => 'foo'); | |
trans(([{g},{h}]) => 'foo'); | |
trans(({a, b = 10}) => a); | |
declare function idCreator<T>(f: (x: T|undefined) => T): T; | |
const icn: number = idCreator(_ => 5); // ZZZ | |
declare function bar<T, U, V>(x: T, y: U, cb: (x: T, y: U) => V): V; | |
declare function id2<T>(x: T, y: T): T; | |
var b1 = bar(1, "one", g); // Should be number | string | |
var b2 = bar(1, "one", id2); // Should be number | string | |
declare function withNum<N extends number>(x: N): N; | |
declare function withString<S extends string>(f: (x: S) => S): void; | |
declare function useString(f: (x: string) => string): void; | |
withString(withNum); // Error | |
useString(withNum); // Error | |
declare function f10<T>(x: T): T; | |
declare function f10<T>(x: T, y: number): T; | |
const a10: string[] = ["a", "b"]; | |
const b10 = a10.map(f10); | |
declare function botox<X, Y>(idX: (x: X) => X, idY: (y: Y) => Y): (x: X, y: Y) => [X, Y]; | |
const xyPair: [number, string] = botox(id, id)(3, 'str'); | |
const testPair: { x: number, y: string } = pair(3)('str'); | |
declare function botox2<X, Y>(idX: { a: (x: X) => X }, idY: { a: (y: Y) => Y }): (x: X, y: Y) => [X, Y]; | |
const bottoxObj = { a: id }; | |
const xyPair2: [number, string] = botox2(bottoxObj, bottoxObj)(3, 'str'); // ZZZ | |
const xyPair3: [number, string] = botox2({ a: id }, { a: id })(3, 'str'); | |
class GenericClass<T> { | |
payload: T; | |
} | |
var genericObject = new GenericClass<{ greeting: string }>(); | |
function genericFunction<T>(object: GenericClass<T>, callback: (payload: T) => void) { | |
callback(object.payload); | |
} | |
genericFunction(genericObject, ({greeting}) => { | |
var s = greeting.toLocaleLowerCase(); // Greeting should be of type string | |
}); | |
class Foo<T extends {a: string; b:number;}>{ | |
test: T; | |
constructor(x: T){} | |
} | |
var x = new Foo(true); // Should error | |
var y = new Foo({a: "test", b: 42}); // Should be OK | |
var z: number = y.test.b; | |
declare function withFew<a, r>(values: a[], haveFew: (values: a[]) => r, haveNone: (reason: string) => r): r; | |
function fail(message: string) : never { throw new Error(message); } | |
const result: number[] = withFew([1, 2, 3], id, fail); // expected result is number[] | |
type List<T> = { kind: 'nil' } | |
| { kind: 'cons', val: T, rest: List<T> } | |
const Nil = { kind: 'nil' as 'nil' } | |
declare function cons<C>(x: C, xs: List<C>): List<C>; | |
declare function foldr<V, A>(list: List<V>, initial: A, f: (x: V, acc: A) => A): A; | |
function concat<C>(list: List<List<C>>): List<C> { | |
return foldr(list, Nil as List<C>, append); | |
} | |
function append<L>(xs: List<L>, ys: List<L>): List<L> { | |
return foldr(xs, ys, cons); | |
} | |
declare function zest<T>(x: T): void; | |
zest(5); // should be number | |
function append2<L>(xs: List<L>, ys: List<L>): List<L> { | |
return foldr(xs, ys, flip(fconst)); // ZZZ | |
} | |
function append3<L>(xs: List<L>, ys: List<L>) { | |
return foldr(xs, ys, flip(fconst)); | |
} | |
function append4<L>(xs: List<L>, ys: List<L>) { | |
return foldr(xs, ys, flip(flip(cons))); | |
} | |
const infPowa: typeof append = append3; // ZZZ | |
let jj = <T>(n: T) => 'Error please?'; | |
let myFunc: <T>(n: T) => T = jj; | |
function foo<T extends Function>(x: T): T { return x; } | |
const r1 = foo(function (x: string) { return x; }); | |
const r2 = foo((x: string) => x); | |
const r3 = foo(function (x: any) { return x; }); | |
declare const cb1: { new <T>(x: T): T }; | |
declare const cb2: { new<T>(x: T): number; new<T>(x: number): T; } | |
declare function foo7<T>(x:T, cb: { new(x: T): string; new(x: T, y?: T): string }): void; | |
foo7(1, cb1); // Should error | |
foo7(1, cb2); | |
function map<A, B>(items: A[], f: (x: A) => B): B[]{ | |
return items.map(f); | |
} | |
var v10: number[] = map([1, 2, 3], id); // Error if not number[] | |
function foo3<T, U>(x: T, cb: (a: T) => U, y: U) { | |
return cb(x); | |
} | |
var r7 = foo3(1, <Z>(a: Z) => '', ''); // string | |
declare var a: { new <T>(x: T): T; }; | |
function foo2<T, U>(x: T, cb: new(a: T) => U) { | |
return new cb(x); | |
} | |
var r4b = foo2(1, a); // number | |
function wf<N extends 5>(n: N, f: (x: 5) => N): N { | |
return f(n); | |
} | |
const wfr: 5 = wf(5, id); | |
const wfr2 = wf(4, id); // error | |
declare function flip<A, B, R>(f: (a: A, b: B) => R): (b: B, a: A) => R; | |
function id<I>(x: I): I { | |
return x; | |
} | |
function fconst<X, Y>(x: X, y: Y): X { | |
return x; | |
} | |
function addStr(x: number, y: string) { | |
return x + y; | |
} | |
function tagged<T extends string, Q>(tag: T, value: Q): { tag: T, value: Q } { | |
return { tag, value }; | |
} | |
function fbound<T extends Q, Q>(tag: T, value: Q): { tag: T, value: Q } { | |
return { tag, value }; | |
} | |
fbound(4, 4).tag; // 4 (better) or number | |
flip(fbound)(4, 4) // OK | |
fbound(4, "4"); // Error | |
flip(fbound)("4", 4) // Error | |
function of2<a, b>(one: a, two: b): [a, b] { | |
return [one, two]; | |
} | |
const flipped = flip(of2); | |
// it was working before | |
const f1 = flip(addStr); // (b: string, a: number) => string | |
const v1 = f1("hello", 3); | |
const v2 = id(id)(3); // `3` | |
// working now | |
const f2 = flip(id); // <T>(b: {}, a: T): T | |
const f3 = flip(fconst); // <Y, X>(b: Y, a: X) => X | |
const f4 = flip(tagged); // <Q, T extends string>(b: Q, a: T) => { tag: T, value: Q } | |
const v3 = f3(1, "qw") // `"qw"` | |
const v4 = f3([], {}) // `{}` | |
const v5 = f4(5, "hello"); // { tag: "hello", value: number } | |
const v6 = f4(5, 5); // Error as expected | |
declare function compose<A, B, C>(f: (b: B) => C, g: (a: A) => B): (a: A) => C; | |
declare const f: <T>(x:number) => T; | |
declare const g: (x:boolean) => number; | |
const f5 = compose(f, g) // OUCH! this gets type `<T>(a: boolean) => T` | |
declare const g_2: <T>(x: T) => boolean; | |
declare const f_2: (x: boolean) => number; | |
const f6 = compose(f_2, g_2) // <T> (a: T) => number | |
const f7 = compose(id, x => String(x)) // (a: {}) => string | |
declare function h<R>(f: (x: number) => R): R; | |
var z: number = h(id); | |
const arr: number[] = [1, 2, 3].map(id); | |
declare const val1: string | undefined; | |
declare function cleanse<T>(x: T|undefined): x is T; | |
cleanse(val1); | |
class MyClass | |
{ | |
one(c: boolean){}; | |
two(){}; | |
} | |
declare const test: PickPrototype<typeof MyClass, 'one'>; | |
type PickPrototype<T extends { prototype: any }, K extends keyof T['prototype']> = { | |
[P in K]: T['prototype'][P]; | |
} | |
function wrap<T>(innerFunc: (data: T) => any) { | |
return (data:T) => innerFunc(data); | |
} | |
function inner(x:number) {}; | |
inner(2); | |
let func = wrap(inner); | |
func(2); | |
declare function union<A, B, C>(f: (a: A|B|C, b: A|B|C, c: A|B|C) => void): void; | |
union(<X, Y, Z>(x: X, y: Y, z: Z) => x) | |
declare function union2<A, B, C>(f: (a: A, b: B, c: C) => void): void; | |
union2(<X, Y, Z>(x: X|Y|Z, y: X|Y|Z, z: X|Y|Z) => x); | |
declare function union3<A, B>(f: (a: A|string, b: A|number) => B): B; | |
declare function uParam31<X>(x: X|number, y: X|string): X; | |
declare function uParam32(x: number, y: number|string): void; | |
declare function uParam33(x: string, y: number|string): void; | |
union3(uParam31); // error; A,X = [number, string] | |
union3(uParam32); // error | |
union3(uParam33); // OK; A = string; B = void | |
declare function union4<A, B, C>(f: (b: A|B) => C, a: A): C; | |
declare function uParam41(y: number|string): void; | |
declare function uParam42<X>(y: number|X): X; | |
declare function uParam43<X>(y: string|X): X; | |
union4(uParam41, 4); // A = number, B = string, C = void | |
union4(uParam42, 4); // A = number, B = X, C = X | |
union4(uParam43, 4); // A = number, B = string, C = number |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment