From b7fe99a88c59bd652029bdfe5b6ba8709a677838 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Sat, 11 May 2019 16:40:23 -0700 Subject: [PATCH] Instantiate constraint with default upon comparison (#31240) --- src/compiler/checker.ts | 2 +- ...tantiatedWithDefaultWhenCheckingDefault.js | 42 +++++++++ ...atedWithDefaultWhenCheckingDefault.symbols | 87 +++++++++++++++++++ ...tiatedWithDefaultWhenCheckingDefault.types | 49 +++++++++++ ...tantiatedWithDefaultWhenCheckingDefault.ts | 24 +++++ 5 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.js create mode 100644 tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.symbols create mode 100644 tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.types create mode 100644 tests/cases/compiler/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cc4c8476de6f5..64834befee1c8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24441,7 +24441,7 @@ namespace ts { const constraintType = getConstraintOfTypeParameter(typeParameter); const defaultType = getDefaultFromTypeParameter(typeParameter); if (constraintType && defaultType) { - checkTypeAssignableTo(defaultType, getTypeWithThisArgument(constraintType, defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); + checkTypeAssignableTo(defaultType, getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); } if (produceDiagnostics) { checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0); diff --git a/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.js b/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.js new file mode 100644 index 0000000000000..fc3922448e9ce --- /dev/null +++ b/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.js @@ -0,0 +1,42 @@ +//// [typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts] +// tricky interface +interface Settable { + set(value: V): T; +} + +// implement +class Identity implements Settable, V> { + readonly item: V; + constructor(value: V) { + this.item = value; + } + public set(value: V): Identity { + return new Identity(value); + } +} + +// generic parameter default +interface Test1 = Identity> { }; +let test1: Test1; + +// not generic parameter default +interface Test2Base> { }; +type Test2 = Test2Base>; +let test2: Test2; + + +//// [typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.js] +// implement +var Identity = /** @class */ (function () { + function Identity(value) { + this.item = value; + } + Identity.prototype.set = function (value) { + return new Identity(value); + }; + return Identity; +}()); +; +var test1; +; +var test2; diff --git a/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.symbols b/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.symbols new file mode 100644 index 0000000000000..3462a11d800f2 --- /dev/null +++ b/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.symbols @@ -0,0 +1,87 @@ +=== tests/cases/compiler/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts === +// tricky interface +interface Settable { +>Settable : Symbol(Settable, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 0, 0)) +>T : Symbol(T, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 1, 19)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 1, 21)) + + set(value: V): T; +>set : Symbol(Settable.set, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 1, 26)) +>value : Symbol(value, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 2, 8)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 1, 21)) +>T : Symbol(T, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 1, 19)) +} + +// implement +class Identity implements Settable, V> { +>Identity : Symbol(Identity, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 3, 1)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) +>Settable : Symbol(Settable, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 0, 0)) +>Identity : Symbol(Identity, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 3, 1)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) + + readonly item: V; +>item : Symbol(Identity.item, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 55)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) + + constructor(value: V) { +>value : Symbol(value, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 8, 16)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) + + this.item = value; +>this.item : Symbol(Identity.item, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 55)) +>this : Symbol(Identity, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 3, 1)) +>item : Symbol(Identity.item, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 55)) +>value : Symbol(value, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 8, 16)) + } + public set(value: V): Identity { +>set : Symbol(Identity.set, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 10, 5)) +>value : Symbol(value, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 11, 15)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) +>Identity : Symbol(Identity, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 3, 1)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) + + return new Identity(value); +>Identity : Symbol(Identity, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 3, 1)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 6, 15)) +>value : Symbol(value, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 11, 15)) + } +} + +// generic parameter default +interface Test1 = Identity> { }; +>Test1 : Symbol(Test1, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 14, 1)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 17, 16)) +>T : Symbol(T, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 17, 18)) +>Settable : Symbol(Settable, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 0, 0)) +>T : Symbol(T, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 17, 18)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 17, 16)) +>Identity : Symbol(Identity, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 3, 1)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 17, 16)) + +let test1: Test1; +>test1 : Symbol(test1, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 18, 3)) +>Test1 : Symbol(Test1, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 14, 1)) + +// not generic parameter default +interface Test2Base> { }; +>Test2Base : Symbol(Test2Base, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 18, 25)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 21, 20)) +>T : Symbol(T, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 21, 22)) +>Settable : Symbol(Settable, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 0, 0)) +>T : Symbol(T, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 21, 22)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 21, 20)) + +type Test2 = Test2Base>; +>Test2 : Symbol(Test2, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 21, 53)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 22, 11)) +>Test2Base : Symbol(Test2Base, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 18, 25)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 22, 11)) +>Identity : Symbol(Identity, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 3, 1)) +>V : Symbol(V, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 22, 11)) + +let test2: Test2; +>test2 : Symbol(test2, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 23, 3)) +>Test2 : Symbol(Test2, Decl(typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts, 21, 53)) + diff --git a/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.types b/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.types new file mode 100644 index 0000000000000..cb3394962c613 --- /dev/null +++ b/tests/baselines/reference/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.types @@ -0,0 +1,49 @@ +=== tests/cases/compiler/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts === +// tricky interface +interface Settable { + set(value: V): T; +>set : (value: V) => T +>value : V +} + +// implement +class Identity implements Settable, V> { +>Identity : Identity + + readonly item: V; +>item : V + + constructor(value: V) { +>value : V + + this.item = value; +>this.item = value : V +>this.item : V +>this : this +>item : V +>value : V + } + public set(value: V): Identity { +>set : (value: V) => Identity +>value : V + + return new Identity(value); +>new Identity(value) : Identity +>Identity : typeof Identity +>value : V + } +} + +// generic parameter default +interface Test1 = Identity> { }; +let test1: Test1; +>test1 : Test1> + +// not generic parameter default +interface Test2Base> { }; +type Test2 = Test2Base>; +>Test2 : Test2Base> + +let test2: Test2; +>test2 : Test2Base> + diff --git a/tests/cases/compiler/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts b/tests/cases/compiler/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts new file mode 100644 index 0000000000000..3f4e3e19c8cf7 --- /dev/null +++ b/tests/cases/compiler/typePartameterConstraintInstantiatedWithDefaultWhenCheckingDefault.ts @@ -0,0 +1,24 @@ +// tricky interface +interface Settable { + set(value: V): T; +} + +// implement +class Identity implements Settable, V> { + readonly item: V; + constructor(value: V) { + this.item = value; + } + public set(value: V): Identity { + return new Identity(value); + } +} + +// generic parameter default +interface Test1 = Identity> { }; +let test1: Test1; + +// not generic parameter default +interface Test2Base> { }; +type Test2 = Test2Base>; +let test2: Test2;