Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ahejlsberg committed Dec 15, 2023
1 parent 411205e commit b25bf3e
Show file tree
Hide file tree
Showing 5 changed files with 975 additions and 0 deletions.
119 changes: 119 additions & 0 deletions tests/baselines/reference/noInfer.errors.txt
Original file line number Diff line number Diff line change
@@ -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<T> is erased for primitives

type T00 = NoInfer<string>;
type T01 = NoInfer<string | number | boolean>;
type T02 = NoInfer<undefined>;
type T03 = NoInfer<"foo">;
type T04 = NoInfer<`foo${string}`>;
type T05 = NoInfer<`foo${string}` & `${string}bar`>;
type T06 = NoInfer<{}>;

// NoInfer<T> is preserved for object types

type T10 = NoInfer<string[]>;
type T11 = NoInfer<{ x: string }>;

// NoInfer<T> is erased if it has no effect

type T20<T> = NoInfer<NoInfer<T>>;
type T21<T> = NoInfer<NoInfer<T> & string>;
type T22<T> = NoInfer<NoInfer<T> & string[]>;

declare function foo1<T extends string>(a: T, b: NoInfer<T>): void
declare function foo2<T extends string>(a: T, b: NoInfer<T>[]): void
declare function foo3<T extends string>(a: T, b: NoInfer<T[]>): void
declare function foo4<T extends string>(a: T, b: { x: NoInfer<T> }): void
declare function foo5<T extends string>(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<T>(value: T, getDefault: () => NoInfer<T>): 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<T>(actual: T, expected: NoInfer<T>): 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<T, R>(func: (value: T) => R, value: NoInfer<T>): 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: Props; };
declare function doWork<Props>(Component: Component<Props>, props: NoInfer<Props>): 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<T>(callback: (a: NoInfer<T>, b: number) => T): T;
const mutate1 = mutate((a, b) => b);

declare class ExampleClass<T> {}
class OkClass<T> {
constructor(private clazz: ExampleClass<T>, private _value: NoInfer<T>) {}

get value(): T {
return this._value; // ok
}
}
class OkClass2<T> {
constructor(private clazz: ExampleClass<T>, public _value: NoInfer<T>) {}
}

185 changes: 185 additions & 0 deletions tests/baselines/reference/noInfer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
//// [tests/cases/conformance/types/typeRelationships/typeInference/noInfer.ts] ////

//// [noInfer.ts]
// NoInfer<T> is erased for primitives

type T00 = NoInfer<string>;
type T01 = NoInfer<string | number | boolean>;
type T02 = NoInfer<undefined>;
type T03 = NoInfer<"foo">;
type T04 = NoInfer<`foo${string}`>;
type T05 = NoInfer<`foo${string}` & `${string}bar`>;
type T06 = NoInfer<{}>;

// NoInfer<T> is preserved for object types

type T10 = NoInfer<string[]>;
type T11 = NoInfer<{ x: string }>;

// NoInfer<T> is erased if it has no effect

type T20<T> = NoInfer<NoInfer<T>>;
type T21<T> = NoInfer<NoInfer<T> & string>;
type T22<T> = NoInfer<NoInfer<T> & string[]>;

declare function foo1<T extends string>(a: T, b: NoInfer<T>): void
declare function foo2<T extends string>(a: T, b: NoInfer<T>[]): void
declare function foo3<T extends string>(a: T, b: NoInfer<T[]>): void
declare function foo4<T extends string>(a: T, b: { x: NoInfer<T> }): void
declare function foo5<T extends string>(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<T>(value: T, getDefault: () => NoInfer<T>): void;

doSomething(new Animal(), () => new Animal()); // ok
doSomething(new Animal(), () => new Dog()); // ok
doSomething(new Dog(), () => new Animal()); // error

declare function assertEqual<T>(actual: T, expected: NoInfer<T>): boolean;

assertEqual({ x: 1 }, { x: 3 }); // ok
const g = { x: 3, y: 2 };
assertEqual(g, { x: 3 }); // error

declare function invoke<T, R>(func: (value: T) => R, value: NoInfer<T>): 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: Props; };
declare function doWork<Props>(Component: Component<Props>, props: NoInfer<Props>): void;
declare const comp: Component<{ foo: number }>;

doWork(comp, { foo: 42 }); // ok
doWork(comp, {}); // error

declare function mutate<T>(callback: (a: NoInfer<T>, b: number) => T): T;
const mutate1 = mutate((a, b) => b);

declare class ExampleClass<T> {}
class OkClass<T> {
constructor(private clazz: ExampleClass<T>, private _value: NoInfer<T>) {}

get value(): T {
return this._value; // ok
}
}
class OkClass2<T> {
constructor(private clazz: ExampleClass<T>, public _value: NoInfer<T>) {}
}


//// [noInfer.js]
"use strict";
// NoInfer<T> 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<string>;
type T01 = NoInfer<string | number | boolean>;
type T02 = NoInfer<undefined>;
type T03 = NoInfer<"foo">;
type T04 = NoInfer<`foo${string}`>;
type T05 = NoInfer<`foo${string}` & `${string}bar`>;
type T06 = NoInfer<{}>;
type T10 = NoInfer<string[]>;
type T11 = NoInfer<{
x: string;
}>;
type T20<T> = NoInfer<NoInfer<T>>;
type T21<T> = NoInfer<NoInfer<T> & string>;
type T22<T> = NoInfer<NoInfer<T> & string[]>;
declare function foo1<T extends string>(a: T, b: NoInfer<T>): void;
declare function foo2<T extends string>(a: T, b: NoInfer<T>[]): void;
declare function foo3<T extends string>(a: T, b: NoInfer<T[]>): void;
declare function foo4<T extends string>(a: T, b: {
x: NoInfer<T>;
}): void;
declare function foo5<T extends string>(a: T, b: NoInfer<{
x: T;
}>): void;
declare class Animal {
move(): void;
}
declare class Dog extends Animal {
woof(): void;
}
declare function doSomething<T>(value: T, getDefault: () => NoInfer<T>): void;
declare function assertEqual<T>(actual: T, expected: NoInfer<T>): boolean;
declare const g: {
x: number;
y: number;
};
declare function invoke<T, R>(func: (value: T) => R, value: NoInfer<T>): R;
declare function test(value: {
x: number;
}): number;
type Component<Props> = {
props: Props;
};
declare function doWork<Props>(Component: Component<Props>, props: NoInfer<Props>): void;
declare const comp: Component<{
foo: number;
}>;
declare function mutate<T>(callback: (a: NoInfer<T>, b: number) => T): T;
declare const mutate1: unknown;
declare class ExampleClass<T> {
}
declare class OkClass<T> {
private clazz;
private _value;
constructor(clazz: ExampleClass<T>, _value: NoInfer<T>);
get value(): T;
}
declare class OkClass2<T> {
private clazz;
_value: NoInfer<T>;
constructor(clazz: ExampleClass<T>, _value: NoInfer<T>);
}
Loading

0 comments on commit b25bf3e

Please sign in to comment.