-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add NoInfer<T>
intrinsic represented as special substitution type
#56794
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
ba7f084
Add NoInfer<T> intrinsic represented as special substitution type
ahejlsberg 411205e
Update tests
ahejlsberg b25bf3e
Add tests
ahejlsberg 9438168
Erase NoInfer<T> in index types
ahejlsberg e492451
Add tests
ahejlsberg 63b6713
keyof NoInfer<T> ==> NoInfer<keyof T> / globalThis emit when needed
ahejlsberg 14b90c2
Simplify keyof NoInfer<T> ==> NoInfer<keyof T> transformation
ahejlsberg 2fc975a
Update tests
ahejlsberg af2aae4
Merge branch 'main' into fix14829
ahejlsberg 79f8513
Add test for redeclaration of NoInfer<T>
ahejlsberg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
noInfer.ts(35,13): error TS2345: Argument of type '"bar"' is not assignable to parameter of type '"foo"'. | ||
noInfer.ts(36,14): error TS2322: Type '"bar"' is not assignable to type '"foo"'. | ||
noInfer.ts(37,14): error TS2322: Type '"bar"' is not assignable to type '"foo"'. | ||
noInfer.ts(38,15): error TS2322: Type '"bar"' is not assignable to type '"foo"'. | ||
noInfer.ts(39,15): error TS2322: Type '"bar"' is not assignable to type '"foo"'. | ||
noInfer.ts(47,30): error TS2741: Property 'woof' is missing in type 'Animal' but required in type 'Dog'. | ||
noInfer.ts(53,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(58,22): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. | ||
noInfer.ts(59,14): error TS2353: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; }'. | ||
noInfer.ts(66,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[]>; | ||
|
||
// keyof NoInfer<T> is transformed into NoInfer<keyof T> | ||
|
||
type T30 = keyof NoInfer<{ a: string, b: string }>; | ||
type T31<T> = keyof NoInfer<T>; | ||
type T32 = { [K in keyof NoInfer<{ a: string, b: string }>]: K }; | ||
|
||
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:31: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:32: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:42:36: 'woof' is declared here. | ||
!!! related TS6502 noInfer.ts:43: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:52: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:63: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>) {} | ||
} | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slightly related question: should
ThisType
become an intrinsic type as well (it is kinda intrinsic by nature but it's not defined as such in the typedefs)? Or is it better to not touch it at all?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obviously this shouldn't be touched as part of this PR - I just take this opportunity to ask a question about it ;p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to leave
ThisType
as is. Anintrinsic
declaration doesn't really say anything about the internal representation of the type, and we already have a perfectly good solution for that with the current interface-based declaration.