From b25bf3ea054f2563020a73dd769e41645e5b968b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 15 Dec 2023 09:19:22 -0800 Subject: [PATCH] Add tests --- tests/baselines/reference/noInfer.errors.txt | 119 +++++++ tests/baselines/reference/noInfer.js | 185 +++++++++++ tests/baselines/reference/noInfer.symbols | 307 ++++++++++++++++++ tests/baselines/reference/noInfer.types | 286 ++++++++++++++++ .../typeInference/noInfer.ts | 78 +++++ 5 files changed, 975 insertions(+) create mode 100644 tests/baselines/reference/noInfer.errors.txt create mode 100644 tests/baselines/reference/noInfer.js create mode 100644 tests/baselines/reference/noInfer.symbols create mode 100644 tests/baselines/reference/noInfer.types create mode 100644 tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts diff --git a/tests/baselines/reference/noInfer.errors.txt b/tests/baselines/reference/noInfer.errors.txt new file mode 100644 index 0000000000000..8bb5c10706b42 --- /dev/null +++ b/tests/baselines/reference/noInfer.errors.txt @@ -0,0 +1,119 @@ +noInfer.ts(29,13): error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. +noInfer.ts(30,14): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +noInfer.ts(31,14): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +noInfer.ts(32,15): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +noInfer.ts(33,15): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +noInfer.ts(41,30): error TS2741: Property 'woof' is missing in type 'Animal' but required in type 'Dog'. +noInfer.ts(47,16): error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type '{ x: number; y: number; }'. + Property 'y' is missing in type '{ x: number; }' but required in type '{ x: number; y: number; }'. +noInfer.ts(52,22): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. +noInfer.ts(53,14): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. +noInfer.ts(60,14): error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. + Property 'foo' is missing in type '{}' but required in type '{ foo: number; }'. + + +==== noInfer.ts (10 errors) ==== + // NoInfer is erased for primitives + + type T00 = NoInfer; + type T01 = NoInfer; + type T02 = NoInfer; + type T03 = NoInfer<"foo">; + type T04 = NoInfer<`foo${string}`>; + type T05 = NoInfer<`foo${string}` & `${string}bar`>; + type T06 = NoInfer<{}>; + + // NoInfer is preserved for object types + + type T10 = NoInfer; + type T11 = NoInfer<{ x: string }>; + + // NoInfer is erased if it has no effect + + type T20 = NoInfer>; + type T21 = NoInfer & string>; + type T22 = NoInfer & string[]>; + + declare function foo1(a: T, b: NoInfer): void + declare function foo2(a: T, b: NoInfer[]): void + declare function foo3(a: T, b: NoInfer): void + declare function foo4(a: T, b: { x: NoInfer }): void + declare function foo5(a: T, b: NoInfer<{ x: T }>): void + + foo1('foo', 'foo') // ok + foo1('foo', 'bar') // error + ~~~~~ +!!! error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. + foo2('foo', ['bar']) // error + ~~~~~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. + foo3('foo', ['bar']) // error + ~~~~~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. + foo4('foo', { x: 'bar' }) // error + ~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. +!!! related TS6500 noInfer.ts:25:52: The expected type comes from property 'x' which is declared here on type '{ x: "foo"; }' + foo5('foo', { x: 'bar' }) // error + ~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. +!!! related TS6500 noInfer.ts:26:60: The expected type comes from property 'x' which is declared here on type 'NoInfer<{ x: "foo"; }>' + + declare class Animal { move(): void } + declare class Dog extends Animal { woof(): void } + declare function doSomething(value: T, getDefault: () => NoInfer): void; + + doSomething(new Animal(), () => new Animal()); // ok + doSomething(new Animal(), () => new Dog()); // ok + doSomething(new Dog(), () => new Animal()); // error + ~~~~~~~~~~~~ +!!! error TS2741: Property 'woof' is missing in type 'Animal' but required in type 'Dog'. +!!! related TS2728 noInfer.ts:36:36: 'woof' is declared here. +!!! related TS6502 noInfer.ts:37:55: The expected type comes from the return type of this signature. + + declare function assertEqual(actual: T, expected: NoInfer): boolean; + + assertEqual({ x: 1 }, { x: 3 }); // ok + const g = { x: 3, y: 2 }; + assertEqual(g, { x: 3 }); // error + ~~~~~~~~ +!!! error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type '{ x: number; y: number; }'. +!!! error TS2345: Property 'y' is missing in type '{ x: number; }' but required in type '{ x: number; y: number; }'. +!!! related TS2728 noInfer.ts:46:19: 'y' is declared here. + + declare function invoke(func: (value: T) => R, value: NoInfer): R; + declare function test(value: { x: number; }): number; + + invoke(test, { x: 1, y: 2 }); // error + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. + test({ x: 1, y: 2 }); // error + ~ +!!! error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. + + type Component = { props: Props; }; + declare function doWork(Component: Component, props: NoInfer): void; + declare const comp: Component<{ foo: number }>; + + doWork(comp, { foo: 42 }); // ok + doWork(comp, {}); // error + ~~ +!!! error TS2345: Argument of type '{}' is not assignable to parameter of type '{ foo: number; }'. +!!! error TS2345: Property 'foo' is missing in type '{}' but required in type '{ foo: number; }'. +!!! related TS2728 noInfer.ts:57:33: 'foo' is declared here. + + declare function mutate(callback: (a: NoInfer, b: number) => T): T; + const mutate1 = mutate((a, b) => b); + + declare class ExampleClass {} + class OkClass { + constructor(private clazz: ExampleClass, private _value: NoInfer) {} + + get value(): T { + return this._value; // ok + } + } + class OkClass2 { + constructor(private clazz: ExampleClass, public _value: NoInfer) {} + } + \ No newline at end of file diff --git a/tests/baselines/reference/noInfer.js b/tests/baselines/reference/noInfer.js new file mode 100644 index 0000000000000..77f55dfb23ba3 --- /dev/null +++ b/tests/baselines/reference/noInfer.js @@ -0,0 +1,185 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts] //// + +//// [noInfer.ts] +// NoInfer is erased for primitives + +type T00 = NoInfer; +type T01 = NoInfer; +type T02 = NoInfer; +type T03 = NoInfer<"foo">; +type T04 = NoInfer<`foo${string}`>; +type T05 = NoInfer<`foo${string}` & `${string}bar`>; +type T06 = NoInfer<{}>; + +// NoInfer is preserved for object types + +type T10 = NoInfer; +type T11 = NoInfer<{ x: string }>; + +// NoInfer is erased if it has no effect + +type T20 = NoInfer>; +type T21 = NoInfer & string>; +type T22 = NoInfer & string[]>; + +declare function foo1(a: T, b: NoInfer): void +declare function foo2(a: T, b: NoInfer[]): void +declare function foo3(a: T, b: NoInfer): void +declare function foo4(a: T, b: { x: NoInfer }): void +declare function foo5(a: T, b: NoInfer<{ x: T }>): void + +foo1('foo', 'foo') // ok +foo1('foo', 'bar') // error +foo2('foo', ['bar']) // error +foo3('foo', ['bar']) // error +foo4('foo', { x: 'bar' }) // error +foo5('foo', { x: 'bar' }) // error + +declare class Animal { move(): void } +declare class Dog extends Animal { woof(): void } +declare function doSomething(value: T, getDefault: () => NoInfer): void; + +doSomething(new Animal(), () => new Animal()); // ok +doSomething(new Animal(), () => new Dog()); // ok +doSomething(new Dog(), () => new Animal()); // error + +declare function assertEqual(actual: T, expected: NoInfer): boolean; + +assertEqual({ x: 1 }, { x: 3 }); // ok +const g = { x: 3, y: 2 }; +assertEqual(g, { x: 3 }); // error + +declare function invoke(func: (value: T) => R, value: NoInfer): R; +declare function test(value: { x: number; }): number; + +invoke(test, { x: 1, y: 2 }); // error +test({ x: 1, y: 2 }); // error + +type Component = { props: Props; }; +declare function doWork(Component: Component, props: NoInfer): void; +declare const comp: Component<{ foo: number }>; + +doWork(comp, { foo: 42 }); // ok +doWork(comp, {}); // error + +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +const mutate1 = mutate((a, b) => b); + +declare class ExampleClass {} +class OkClass { + constructor(private clazz: ExampleClass, private _value: NoInfer) {} + + get value(): T { + return this._value; // ok + } +} +class OkClass2 { + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +} + + +//// [noInfer.js] +"use strict"; +// NoInfer is erased for primitives +foo1('foo', 'foo'); // ok +foo1('foo', 'bar'); // error +foo2('foo', ['bar']); // error +foo3('foo', ['bar']); // error +foo4('foo', { x: 'bar' }); // error +foo5('foo', { x: 'bar' }); // error +doSomething(new Animal(), function () { return new Animal(); }); // ok +doSomething(new Animal(), function () { return new Dog(); }); // ok +doSomething(new Dog(), function () { return new Animal(); }); // error +assertEqual({ x: 1 }, { x: 3 }); // ok +var g = { x: 3, y: 2 }; +assertEqual(g, { x: 3 }); // error +invoke(test, { x: 1, y: 2 }); // error +test({ x: 1, y: 2 }); // error +doWork(comp, { foo: 42 }); // ok +doWork(comp, {}); // error +var mutate1 = mutate(function (a, b) { return b; }); +var OkClass = /** @class */ (function () { + function OkClass(clazz, _value) { + this.clazz = clazz; + this._value = _value; + } + Object.defineProperty(OkClass.prototype, "value", { + get: function () { + return this._value; // ok + }, + enumerable: false, + configurable: true + }); + return OkClass; +}()); +var OkClass2 = /** @class */ (function () { + function OkClass2(clazz, _value) { + this.clazz = clazz; + this._value = _value; + } + return OkClass2; +}()); + + +//// [noInfer.d.ts] +type T00 = NoInfer; +type T01 = NoInfer; +type T02 = NoInfer; +type T03 = NoInfer<"foo">; +type T04 = NoInfer<`foo${string}`>; +type T05 = NoInfer<`foo${string}` & `${string}bar`>; +type T06 = NoInfer<{}>; +type T10 = NoInfer; +type T11 = NoInfer<{ + x: string; +}>; +type T20 = NoInfer>; +type T21 = NoInfer & string>; +type T22 = NoInfer & string[]>; +declare function foo1(a: T, b: NoInfer): void; +declare function foo2(a: T, b: NoInfer[]): void; +declare function foo3(a: T, b: NoInfer): void; +declare function foo4(a: T, b: { + x: NoInfer; +}): void; +declare function foo5(a: T, b: NoInfer<{ + x: T; +}>): void; +declare class Animal { + move(): void; +} +declare class Dog extends Animal { + woof(): void; +} +declare function doSomething(value: T, getDefault: () => NoInfer): void; +declare function assertEqual(actual: T, expected: NoInfer): boolean; +declare const g: { + x: number; + y: number; +}; +declare function invoke(func: (value: T) => R, value: NoInfer): R; +declare function test(value: { + x: number; +}): number; +type Component = { + props: Props; +}; +declare function doWork(Component: Component, props: NoInfer): void; +declare const comp: Component<{ + foo: number; +}>; +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +declare const mutate1: unknown; +declare class ExampleClass { +} +declare class OkClass { + private clazz; + private _value; + constructor(clazz: ExampleClass, _value: NoInfer); + get value(): T; +} +declare class OkClass2 { + private clazz; + _value: NoInfer; + constructor(clazz: ExampleClass, _value: NoInfer); +} diff --git a/tests/baselines/reference/noInfer.symbols b/tests/baselines/reference/noInfer.symbols new file mode 100644 index 0000000000000..67d5ca7538a57 --- /dev/null +++ b/tests/baselines/reference/noInfer.symbols @@ -0,0 +1,307 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts] //// + +=== noInfer.ts === +// NoInfer is erased for primitives + +type T00 = NoInfer; +>T00 : Symbol(T00, Decl(noInfer.ts, 0, 0)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +type T01 = NoInfer; +>T01 : Symbol(T01, Decl(noInfer.ts, 2, 27)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +type T02 = NoInfer; +>T02 : Symbol(T02, Decl(noInfer.ts, 3, 46)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +type T03 = NoInfer<"foo">; +>T03 : Symbol(T03, Decl(noInfer.ts, 4, 30)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +type T04 = NoInfer<`foo${string}`>; +>T04 : Symbol(T04, Decl(noInfer.ts, 5, 26)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +type T05 = NoInfer<`foo${string}` & `${string}bar`>; +>T05 : Symbol(T05, Decl(noInfer.ts, 6, 35)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +type T06 = NoInfer<{}>; +>T06 : Symbol(T06, Decl(noInfer.ts, 7, 52)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +// NoInfer is preserved for object types + +type T10 = NoInfer; +>T10 : Symbol(T10, Decl(noInfer.ts, 8, 23)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) + +type T11 = NoInfer<{ x: string }>; +>T11 : Symbol(T11, Decl(noInfer.ts, 12, 29)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(noInfer.ts, 13, 20)) + +// NoInfer is erased if it has no effect + +type T20 = NoInfer>; +>T20 : Symbol(T20, Decl(noInfer.ts, 13, 34)) +>T : Symbol(T, Decl(noInfer.ts, 17, 9)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 17, 9)) + +type T21 = NoInfer & string>; +>T21 : Symbol(T21, Decl(noInfer.ts, 17, 34)) +>T : Symbol(T, Decl(noInfer.ts, 18, 9)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 18, 9)) + +type T22 = NoInfer & string[]>; +>T22 : Symbol(T22, Decl(noInfer.ts, 18, 43)) +>T : Symbol(T, Decl(noInfer.ts, 19, 9)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 19, 9)) + +declare function foo1(a: T, b: NoInfer): void +>foo1 : Symbol(foo1, Decl(noInfer.ts, 19, 45)) +>T : Symbol(T, Decl(noInfer.ts, 21, 22)) +>a : Symbol(a, Decl(noInfer.ts, 21, 40)) +>T : Symbol(T, Decl(noInfer.ts, 21, 22)) +>b : Symbol(b, Decl(noInfer.ts, 21, 45)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 21, 22)) + +declare function foo2(a: T, b: NoInfer[]): void +>foo2 : Symbol(foo2, Decl(noInfer.ts, 21, 66)) +>T : Symbol(T, Decl(noInfer.ts, 22, 22)) +>a : Symbol(a, Decl(noInfer.ts, 22, 40)) +>T : Symbol(T, Decl(noInfer.ts, 22, 22)) +>b : Symbol(b, Decl(noInfer.ts, 22, 45)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 22, 22)) + +declare function foo3(a: T, b: NoInfer): void +>foo3 : Symbol(foo3, Decl(noInfer.ts, 22, 68)) +>T : Symbol(T, Decl(noInfer.ts, 23, 22)) +>a : Symbol(a, Decl(noInfer.ts, 23, 40)) +>T : Symbol(T, Decl(noInfer.ts, 23, 22)) +>b : Symbol(b, Decl(noInfer.ts, 23, 45)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 23, 22)) + +declare function foo4(a: T, b: { x: NoInfer }): void +>foo4 : Symbol(foo4, Decl(noInfer.ts, 23, 68)) +>T : Symbol(T, Decl(noInfer.ts, 24, 22)) +>a : Symbol(a, Decl(noInfer.ts, 24, 40)) +>T : Symbol(T, Decl(noInfer.ts, 24, 22)) +>b : Symbol(b, Decl(noInfer.ts, 24, 45)) +>x : Symbol(x, Decl(noInfer.ts, 24, 50)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 24, 22)) + +declare function foo5(a: T, b: NoInfer<{ x: T }>): void +>foo5 : Symbol(foo5, Decl(noInfer.ts, 24, 73)) +>T : Symbol(T, Decl(noInfer.ts, 25, 22)) +>a : Symbol(a, Decl(noInfer.ts, 25, 40)) +>T : Symbol(T, Decl(noInfer.ts, 25, 22)) +>b : Symbol(b, Decl(noInfer.ts, 25, 45)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(noInfer.ts, 25, 58)) +>T : Symbol(T, Decl(noInfer.ts, 25, 22)) + +foo1('foo', 'foo') // ok +>foo1 : Symbol(foo1, Decl(noInfer.ts, 19, 45)) + +foo1('foo', 'bar') // error +>foo1 : Symbol(foo1, Decl(noInfer.ts, 19, 45)) + +foo2('foo', ['bar']) // error +>foo2 : Symbol(foo2, Decl(noInfer.ts, 21, 66)) + +foo3('foo', ['bar']) // error +>foo3 : Symbol(foo3, Decl(noInfer.ts, 22, 68)) + +foo4('foo', { x: 'bar' }) // error +>foo4 : Symbol(foo4, Decl(noInfer.ts, 23, 68)) +>x : Symbol(x, Decl(noInfer.ts, 31, 13)) + +foo5('foo', { x: 'bar' }) // error +>foo5 : Symbol(foo5, Decl(noInfer.ts, 24, 73)) +>x : Symbol(x, Decl(noInfer.ts, 32, 13)) + +declare class Animal { move(): void } +>Animal : Symbol(Animal, Decl(noInfer.ts, 32, 25)) +>move : Symbol(Animal.move, Decl(noInfer.ts, 34, 22)) + +declare class Dog extends Animal { woof(): void } +>Dog : Symbol(Dog, Decl(noInfer.ts, 34, 37)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 32, 25)) +>woof : Symbol(Dog.woof, Decl(noInfer.ts, 35, 34)) + +declare function doSomething(value: T, getDefault: () => NoInfer): void; +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 35, 49)) +>T : Symbol(T, Decl(noInfer.ts, 36, 29)) +>value : Symbol(value, Decl(noInfer.ts, 36, 32)) +>T : Symbol(T, Decl(noInfer.ts, 36, 29)) +>getDefault : Symbol(getDefault, Decl(noInfer.ts, 36, 41)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 36, 29)) + +doSomething(new Animal(), () => new Animal()); // ok +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 35, 49)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 32, 25)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 32, 25)) + +doSomething(new Animal(), () => new Dog()); // ok +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 35, 49)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 32, 25)) +>Dog : Symbol(Dog, Decl(noInfer.ts, 34, 37)) + +doSomething(new Dog(), () => new Animal()); // error +>doSomething : Symbol(doSomething, Decl(noInfer.ts, 35, 49)) +>Dog : Symbol(Dog, Decl(noInfer.ts, 34, 37)) +>Animal : Symbol(Animal, Decl(noInfer.ts, 32, 25)) + +declare function assertEqual(actual: T, expected: NoInfer): boolean; +>assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 40, 43)) +>T : Symbol(T, Decl(noInfer.ts, 42, 29)) +>actual : Symbol(actual, Decl(noInfer.ts, 42, 32)) +>T : Symbol(T, Decl(noInfer.ts, 42, 29)) +>expected : Symbol(expected, Decl(noInfer.ts, 42, 42)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 42, 29)) + +assertEqual({ x: 1 }, { x: 3 }); // ok +>assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 40, 43)) +>x : Symbol(x, Decl(noInfer.ts, 44, 13)) +>x : Symbol(x, Decl(noInfer.ts, 44, 23)) + +const g = { x: 3, y: 2 }; +>g : Symbol(g, Decl(noInfer.ts, 45, 5)) +>x : Symbol(x, Decl(noInfer.ts, 45, 11)) +>y : Symbol(y, Decl(noInfer.ts, 45, 17)) + +assertEqual(g, { x: 3 }); // error +>assertEqual : Symbol(assertEqual, Decl(noInfer.ts, 40, 43)) +>g : Symbol(g, Decl(noInfer.ts, 45, 5)) +>x : Symbol(x, Decl(noInfer.ts, 46, 16)) + +declare function invoke(func: (value: T) => R, value: NoInfer): R; +>invoke : Symbol(invoke, Decl(noInfer.ts, 46, 25)) +>T : Symbol(T, Decl(noInfer.ts, 48, 24)) +>R : Symbol(R, Decl(noInfer.ts, 48, 26)) +>func : Symbol(func, Decl(noInfer.ts, 48, 30)) +>value : Symbol(value, Decl(noInfer.ts, 48, 37)) +>T : Symbol(T, Decl(noInfer.ts, 48, 24)) +>R : Symbol(R, Decl(noInfer.ts, 48, 26)) +>value : Symbol(value, Decl(noInfer.ts, 48, 52)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 48, 24)) +>R : Symbol(R, Decl(noInfer.ts, 48, 26)) + +declare function test(value: { x: number; }): number; +>test : Symbol(test, Decl(noInfer.ts, 48, 75)) +>value : Symbol(value, Decl(noInfer.ts, 49, 22)) +>x : Symbol(x, Decl(noInfer.ts, 49, 30)) + +invoke(test, { x: 1, y: 2 }); // error +>invoke : Symbol(invoke, Decl(noInfer.ts, 46, 25)) +>test : Symbol(test, Decl(noInfer.ts, 48, 75)) +>x : Symbol(x, Decl(noInfer.ts, 51, 14)) +>y : Symbol(y, Decl(noInfer.ts, 51, 20)) + +test({ x: 1, y: 2 }); // error +>test : Symbol(test, Decl(noInfer.ts, 48, 75)) +>x : Symbol(x, Decl(noInfer.ts, 52, 6)) +>y : Symbol(y, Decl(noInfer.ts, 52, 12)) + +type Component = { props: Props; }; +>Component : Symbol(Component, Decl(noInfer.ts, 52, 21)) +>Props : Symbol(Props, Decl(noInfer.ts, 54, 15)) +>props : Symbol(props, Decl(noInfer.ts, 54, 25)) +>Props : Symbol(Props, Decl(noInfer.ts, 54, 15)) + +declare function doWork(Component: Component, props: NoInfer): void; +>doWork : Symbol(doWork, Decl(noInfer.ts, 54, 42)) +>Props : Symbol(Props, Decl(noInfer.ts, 55, 24)) +>Component : Symbol(Component, Decl(noInfer.ts, 55, 31)) +>Component : Symbol(Component, Decl(noInfer.ts, 52, 21)) +>Props : Symbol(Props, Decl(noInfer.ts, 55, 24)) +>props : Symbol(props, Decl(noInfer.ts, 55, 59)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>Props : Symbol(Props, Decl(noInfer.ts, 55, 24)) + +declare const comp: Component<{ foo: number }>; +>comp : Symbol(comp, Decl(noInfer.ts, 56, 13)) +>Component : Symbol(Component, Decl(noInfer.ts, 52, 21)) +>foo : Symbol(foo, Decl(noInfer.ts, 56, 31)) + +doWork(comp, { foo: 42 }); // ok +>doWork : Symbol(doWork, Decl(noInfer.ts, 54, 42)) +>comp : Symbol(comp, Decl(noInfer.ts, 56, 13)) +>foo : Symbol(foo, Decl(noInfer.ts, 58, 14)) + +doWork(comp, {}); // error +>doWork : Symbol(doWork, Decl(noInfer.ts, 54, 42)) +>comp : Symbol(comp, Decl(noInfer.ts, 56, 13)) + +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +>mutate : Symbol(mutate, Decl(noInfer.ts, 59, 17)) +>T : Symbol(T, Decl(noInfer.ts, 61, 24)) +>callback : Symbol(callback, Decl(noInfer.ts, 61, 27)) +>a : Symbol(a, Decl(noInfer.ts, 61, 38)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 61, 24)) +>b : Symbol(b, Decl(noInfer.ts, 61, 52)) +>T : Symbol(T, Decl(noInfer.ts, 61, 24)) +>T : Symbol(T, Decl(noInfer.ts, 61, 24)) + +const mutate1 = mutate((a, b) => b); +>mutate1 : Symbol(mutate1, Decl(noInfer.ts, 62, 5)) +>mutate : Symbol(mutate, Decl(noInfer.ts, 59, 17)) +>a : Symbol(a, Decl(noInfer.ts, 62, 24)) +>b : Symbol(b, Decl(noInfer.ts, 62, 26)) +>b : Symbol(b, Decl(noInfer.ts, 62, 26)) + +declare class ExampleClass {} +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 62, 36)) +>T : Symbol(T, Decl(noInfer.ts, 64, 27)) + +class OkClass { +>OkClass : Symbol(OkClass, Decl(noInfer.ts, 64, 32)) +>T : Symbol(T, Decl(noInfer.ts, 65, 14)) + + constructor(private clazz: ExampleClass, private _value: NoInfer) {} +>clazz : Symbol(OkClass.clazz, Decl(noInfer.ts, 66, 16)) +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 62, 36)) +>T : Symbol(T, Decl(noInfer.ts, 65, 14)) +>_value : Symbol(OkClass._value, Decl(noInfer.ts, 66, 47)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 65, 14)) + + get value(): T { +>value : Symbol(OkClass.value, Decl(noInfer.ts, 66, 78)) +>T : Symbol(T, Decl(noInfer.ts, 65, 14)) + + return this._value; // ok +>this._value : Symbol(OkClass._value, Decl(noInfer.ts, 66, 47)) +>this : Symbol(OkClass, Decl(noInfer.ts, 64, 32)) +>_value : Symbol(OkClass._value, Decl(noInfer.ts, 66, 47)) + } +} +class OkClass2 { +>OkClass2 : Symbol(OkClass2, Decl(noInfer.ts, 71, 1)) +>T : Symbol(T, Decl(noInfer.ts, 72, 15)) + + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +>clazz : Symbol(OkClass2.clazz, Decl(noInfer.ts, 73, 16)) +>ExampleClass : Symbol(ExampleClass, Decl(noInfer.ts, 62, 36)) +>T : Symbol(T, Decl(noInfer.ts, 72, 15)) +>_value : Symbol(OkClass2._value, Decl(noInfer.ts, 73, 47)) +>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(noInfer.ts, 72, 15)) +} + diff --git a/tests/baselines/reference/noInfer.types b/tests/baselines/reference/noInfer.types new file mode 100644 index 0000000000000..c1427c8878daf --- /dev/null +++ b/tests/baselines/reference/noInfer.types @@ -0,0 +1,286 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts] //// + +=== noInfer.ts === +// NoInfer is erased for primitives + +type T00 = NoInfer; +>T00 : string + +type T01 = NoInfer; +>T01 : string | number | boolean + +type T02 = NoInfer; +>T02 : undefined + +type T03 = NoInfer<"foo">; +>T03 : "foo" + +type T04 = NoInfer<`foo${string}`>; +>T04 : `foo${string}` + +type T05 = NoInfer<`foo${string}` & `${string}bar`>; +>T05 : `foo${string}` & `${string}bar` + +type T06 = NoInfer<{}>; +>T06 : {} + +// NoInfer is preserved for object types + +type T10 = NoInfer; +>T10 : NoInfer + +type T11 = NoInfer<{ x: string }>; +>T11 : NoInfer<{ x: string; }> +>x : string + +// NoInfer is erased if it has no effect + +type T20 = NoInfer>; +>T20 : NoInfer + +type T21 = NoInfer & string>; +>T21 : NoInfer & string + +type T22 = NoInfer & string[]>; +>T22 : NoInfer & string[]> + +declare function foo1(a: T, b: NoInfer): void +>foo1 : (a: T, b: NoInfer) => void +>a : T +>b : NoInfer + +declare function foo2(a: T, b: NoInfer[]): void +>foo2 : (a: T, b: NoInfer[]) => void +>a : T +>b : NoInfer[] + +declare function foo3(a: T, b: NoInfer): void +>foo3 : (a: T, b: NoInfer) => void +>a : T +>b : NoInfer + +declare function foo4(a: T, b: { x: NoInfer }): void +>foo4 : (a: T, b: { x: NoInfer;}) => void +>a : T +>b : { x: NoInfer; } +>x : NoInfer + +declare function foo5(a: T, b: NoInfer<{ x: T }>): void +>foo5 : (a: T, b: NoInfer<{ x: T;}>) => void +>a : T +>b : NoInfer<{ x: T; }> +>x : T + +foo1('foo', 'foo') // ok +>foo1('foo', 'foo') : void +>foo1 : (a: T, b: NoInfer) => void +>'foo' : "foo" +>'foo' : "foo" + +foo1('foo', 'bar') // error +>foo1('foo', 'bar') : void +>foo1 : (a: T, b: NoInfer) => void +>'foo' : "foo" +>'bar' : "bar" + +foo2('foo', ['bar']) // error +>foo2('foo', ['bar']) : void +>foo2 : (a: T, b: NoInfer[]) => void +>'foo' : "foo" +>['bar'] : "bar"[] +>'bar' : "bar" + +foo3('foo', ['bar']) // error +>foo3('foo', ['bar']) : void +>foo3 : (a: T, b: NoInfer) => void +>'foo' : "foo" +>['bar'] : "bar"[] +>'bar' : "bar" + +foo4('foo', { x: 'bar' }) // error +>foo4('foo', { x: 'bar' }) : void +>foo4 : (a: T, b: { x: NoInfer; }) => void +>'foo' : "foo" +>{ x: 'bar' } : { x: "bar"; } +>x : "bar" +>'bar' : "bar" + +foo5('foo', { x: 'bar' }) // error +>foo5('foo', { x: 'bar' }) : void +>foo5 : (a: T, b: NoInfer<{ x: T; }>) => void +>'foo' : "foo" +>{ x: 'bar' } : { x: "bar"; } +>x : "bar" +>'bar' : "bar" + +declare class Animal { move(): void } +>Animal : Animal +>move : () => void + +declare class Dog extends Animal { woof(): void } +>Dog : Dog +>Animal : Animal +>woof : () => void + +declare function doSomething(value: T, getDefault: () => NoInfer): void; +>doSomething : (value: T, getDefault: () => NoInfer) => void +>value : T +>getDefault : () => NoInfer + +doSomething(new Animal(), () => new Animal()); // ok +>doSomething(new Animal(), () => new Animal()) : void +>doSomething : (value: T, getDefault: () => NoInfer) => void +>new Animal() : Animal +>Animal : typeof Animal +>() => new Animal() : () => Animal +>new Animal() : Animal +>Animal : typeof Animal + +doSomething(new Animal(), () => new Dog()); // ok +>doSomething(new Animal(), () => new Dog()) : void +>doSomething : (value: T, getDefault: () => NoInfer) => void +>new Animal() : Animal +>Animal : typeof Animal +>() => new Dog() : () => Dog +>new Dog() : Dog +>Dog : typeof Dog + +doSomething(new Dog(), () => new Animal()); // error +>doSomething(new Dog(), () => new Animal()) : void +>doSomething : (value: T, getDefault: () => NoInfer) => void +>new Dog() : Dog +>Dog : typeof Dog +>() => new Animal() : () => Animal +>new Animal() : Animal +>Animal : typeof Animal + +declare function assertEqual(actual: T, expected: NoInfer): boolean; +>assertEqual : (actual: T, expected: NoInfer) => boolean +>actual : T +>expected : NoInfer + +assertEqual({ x: 1 }, { x: 3 }); // ok +>assertEqual({ x: 1 }, { x: 3 }) : boolean +>assertEqual : (actual: T, expected: NoInfer) => boolean +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 +>{ x: 3 } : { x: number; } +>x : number +>3 : 3 + +const g = { x: 3, y: 2 }; +>g : { x: number; y: number; } +>{ x: 3, y: 2 } : { x: number; y: number; } +>x : number +>3 : 3 +>y : number +>2 : 2 + +assertEqual(g, { x: 3 }); // error +>assertEqual(g, { x: 3 }) : boolean +>assertEqual : (actual: T, expected: NoInfer) => boolean +>g : { x: number; y: number; } +>{ x: 3 } : { x: number; } +>x : number +>3 : 3 + +declare function invoke(func: (value: T) => R, value: NoInfer): R; +>invoke : (func: (value: T) => R, value: NoInfer) => R +>func : (value: T) => R +>value : T +>value : NoInfer + +declare function test(value: { x: number; }): number; +>test : (value: { x: number;}) => number +>value : { x: number; } +>x : number + +invoke(test, { x: 1, y: 2 }); // error +>invoke(test, { x: 1, y: 2 }) : number +>invoke : (func: (value: T) => R, value: NoInfer) => R +>test : (value: { x: number; }) => number +>{ x: 1, y: 2 } : { x: number; y: number; } +>x : number +>1 : 1 +>y : number +>2 : 2 + +test({ x: 1, y: 2 }); // error +>test({ x: 1, y: 2 }) : number +>test : (value: { x: number; }) => number +>{ x: 1, y: 2 } : { x: number; y: number; } +>x : number +>1 : 1 +>y : number +>2 : 2 + +type Component = { props: Props; }; +>Component : Component +>props : Props + +declare function doWork(Component: Component, props: NoInfer): void; +>doWork : (Component: Component, props: NoInfer) => void +>Component : Component +>props : NoInfer + +declare const comp: Component<{ foo: number }>; +>comp : Component<{ foo: number; }> +>foo : number + +doWork(comp, { foo: 42 }); // ok +>doWork(comp, { foo: 42 }) : void +>doWork : (Component: Component, props: NoInfer) => void +>comp : Component<{ foo: number; }> +>{ foo: 42 } : { foo: number; } +>foo : number +>42 : 42 + +doWork(comp, {}); // error +>doWork(comp, {}) : void +>doWork : (Component: Component, props: NoInfer) => void +>comp : Component<{ foo: number; }> +>{} : {} + +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +>mutate : (callback: (a: NoInfer, b: number) => T) => T +>callback : (a: NoInfer, b: number) => T +>a : NoInfer +>b : number + +const mutate1 = mutate((a, b) => b); +>mutate1 : unknown +>mutate((a, b) => b) : unknown +>mutate : (callback: (a: NoInfer, b: number) => T) => T +>(a, b) => b : (a: unknown, b: number) => number +>a : unknown +>b : number +>b : number + +declare class ExampleClass {} +>ExampleClass : ExampleClass + +class OkClass { +>OkClass : OkClass + + constructor(private clazz: ExampleClass, private _value: NoInfer) {} +>clazz : ExampleClass +>_value : NoInfer + + get value(): T { +>value : T + + return this._value; // ok +>this._value : NoInfer +>this : this +>_value : NoInfer + } +} +class OkClass2 { +>OkClass2 : OkClass2 + + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +>clazz : ExampleClass +>_value : NoInfer +} + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts b/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts new file mode 100644 index 0000000000000..30296f2a7cba3 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts @@ -0,0 +1,78 @@ +// @strict: true +// @declaration: true + +// NoInfer is erased for primitives + +type T00 = NoInfer; +type T01 = NoInfer; +type T02 = NoInfer; +type T03 = NoInfer<"foo">; +type T04 = NoInfer<`foo${string}`>; +type T05 = NoInfer<`foo${string}` & `${string}bar`>; +type T06 = NoInfer<{}>; + +// NoInfer is preserved for object types + +type T10 = NoInfer; +type T11 = NoInfer<{ x: string }>; + +// NoInfer is erased if it has no effect + +type T20 = NoInfer>; +type T21 = NoInfer & string>; +type T22 = NoInfer & string[]>; + +declare function foo1(a: T, b: NoInfer): void +declare function foo2(a: T, b: NoInfer[]): void +declare function foo3(a: T, b: NoInfer): void +declare function foo4(a: T, b: { x: NoInfer }): void +declare function foo5(a: T, b: NoInfer<{ x: T }>): void + +foo1('foo', 'foo') // ok +foo1('foo', 'bar') // error +foo2('foo', ['bar']) // error +foo3('foo', ['bar']) // error +foo4('foo', { x: 'bar' }) // error +foo5('foo', { x: 'bar' }) // error + +declare class Animal { move(): void } +declare class Dog extends Animal { woof(): void } +declare function doSomething(value: T, getDefault: () => NoInfer): void; + +doSomething(new Animal(), () => new Animal()); // ok +doSomething(new Animal(), () => new Dog()); // ok +doSomething(new Dog(), () => new Animal()); // error + +declare function assertEqual(actual: T, expected: NoInfer): boolean; + +assertEqual({ x: 1 }, { x: 3 }); // ok +const g = { x: 3, y: 2 }; +assertEqual(g, { x: 3 }); // error + +declare function invoke(func: (value: T) => R, value: NoInfer): R; +declare function test(value: { x: number; }): number; + +invoke(test, { x: 1, y: 2 }); // error +test({ x: 1, y: 2 }); // error + +type Component = { props: Props; }; +declare function doWork(Component: Component, props: NoInfer): void; +declare const comp: Component<{ foo: number }>; + +doWork(comp, { foo: 42 }); // ok +doWork(comp, {}); // error + +declare function mutate(callback: (a: NoInfer, b: number) => T): T; +const mutate1 = mutate((a, b) => b); + +declare class ExampleClass {} +class OkClass { + constructor(private clazz: ExampleClass, private _value: NoInfer) {} + + get value(): T { + return this._value; // ok + } +} +class OkClass2 { + constructor(private clazz: ExampleClass, public _value: NoInfer) {} +}