diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f79b04904b1c6..80e17ea86a221 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11295,7 +11295,7 @@ namespace ts { } else { const sub = instantiateType((type).substitute, mapper); - if (sub.flags & TypeFlags.AnyOrUnknown || isTypeSubtypeOf(getRestrictiveInstantiation(maybeVariable), getRestrictiveInstantiation(sub))) { + if (sub.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(maybeVariable), getRestrictiveInstantiation(sub))) { return maybeVariable; } return sub; diff --git a/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.js b/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.js new file mode 100644 index 0000000000000..722483f5f553d --- /dev/null +++ b/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.js @@ -0,0 +1,33 @@ +//// [substitutionTypeNoMergeOfAssignableType.ts] +interface Entry { + comment?: string; + } + + interface Entity { + fields: {[key: string]: Entry}; + } + + type Fields = { + [P in keyof E["fields"]]: E["fields"][P] + }; + + type Nodes = { + [P in keyof T]: T[P] extends Entity + ? Fields + : T[P] + }; + + function makeEntityStore>(config: T): Nodes { + return {} as Nodes + } + + const myTest = makeEntityStore({ test: { fields: { id: {} } } }); + myTest.test + + +//// [substitutionTypeNoMergeOfAssignableType.js] +function makeEntityStore(config) { + return {}; +} +var myTest = makeEntityStore({ test: { fields: { id: {} } } }); +myTest.test; diff --git a/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.symbols b/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.symbols new file mode 100644 index 0000000000000..4d1641b535516 --- /dev/null +++ b/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.symbols @@ -0,0 +1,79 @@ +=== tests/cases/compiler/substitutionTypeNoMergeOfAssignableType.ts === +interface Entry { +>Entry : Symbol(Entry, Decl(substitutionTypeNoMergeOfAssignableType.ts, 0, 0)) + + comment?: string; +>comment : Symbol(Entry.comment, Decl(substitutionTypeNoMergeOfAssignableType.ts, 0, 17)) + } + + interface Entity { +>Entity : Symbol(Entity, Decl(substitutionTypeNoMergeOfAssignableType.ts, 2, 2)) + + fields: {[key: string]: Entry}; +>fields : Symbol(Entity.fields, Decl(substitutionTypeNoMergeOfAssignableType.ts, 4, 19)) +>key : Symbol(key, Decl(substitutionTypeNoMergeOfAssignableType.ts, 5, 15)) +>Entry : Symbol(Entry, Decl(substitutionTypeNoMergeOfAssignableType.ts, 0, 0)) + } + + type Fields = { +>Fields : Symbol(Fields, Decl(substitutionTypeNoMergeOfAssignableType.ts, 6, 2)) +>E : Symbol(E, Decl(substitutionTypeNoMergeOfAssignableType.ts, 8, 13)) +>Entity : Symbol(Entity, Decl(substitutionTypeNoMergeOfAssignableType.ts, 2, 2)) + + [P in keyof E["fields"]]: E["fields"][P] +>P : Symbol(P, Decl(substitutionTypeNoMergeOfAssignableType.ts, 9, 6)) +>E : Symbol(E, Decl(substitutionTypeNoMergeOfAssignableType.ts, 8, 13)) +>E : Symbol(E, Decl(substitutionTypeNoMergeOfAssignableType.ts, 8, 13)) +>P : Symbol(P, Decl(substitutionTypeNoMergeOfAssignableType.ts, 9, 6)) + + }; + + type Nodes = { +>Nodes : Symbol(Nodes, Decl(substitutionTypeNoMergeOfAssignableType.ts, 10, 3)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 12, 12)) + + [P in keyof T]: T[P] extends Entity +>P : Symbol(P, Decl(substitutionTypeNoMergeOfAssignableType.ts, 13, 6)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 12, 12)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 12, 12)) +>P : Symbol(P, Decl(substitutionTypeNoMergeOfAssignableType.ts, 13, 6)) +>Entity : Symbol(Entity, Decl(substitutionTypeNoMergeOfAssignableType.ts, 2, 2)) + + ? Fields +>Fields : Symbol(Fields, Decl(substitutionTypeNoMergeOfAssignableType.ts, 6, 2)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 12, 12)) +>P : Symbol(P, Decl(substitutionTypeNoMergeOfAssignableType.ts, 13, 6)) + + : T[P] +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 12, 12)) +>P : Symbol(P, Decl(substitutionTypeNoMergeOfAssignableType.ts, 13, 6)) + + }; + + function makeEntityStore>(config: T): Nodes { +>makeEntityStore : Symbol(makeEntityStore, Decl(substitutionTypeNoMergeOfAssignableType.ts, 16, 3)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 18, 26)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Entity : Symbol(Entity, Decl(substitutionTypeNoMergeOfAssignableType.ts, 2, 2)) +>config : Symbol(config, Decl(substitutionTypeNoMergeOfAssignableType.ts, 18, 60)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 18, 26)) +>Nodes : Symbol(Nodes, Decl(substitutionTypeNoMergeOfAssignableType.ts, 10, 3)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 18, 26)) + + return {} as Nodes +>Nodes : Symbol(Nodes, Decl(substitutionTypeNoMergeOfAssignableType.ts, 10, 3)) +>T : Symbol(T, Decl(substitutionTypeNoMergeOfAssignableType.ts, 18, 26)) + } + + const myTest = makeEntityStore({ test: { fields: { id: {} } } }); +>myTest : Symbol(myTest, Decl(substitutionTypeNoMergeOfAssignableType.ts, 22, 6)) +>makeEntityStore : Symbol(makeEntityStore, Decl(substitutionTypeNoMergeOfAssignableType.ts, 16, 3)) +>test : Symbol(test, Decl(substitutionTypeNoMergeOfAssignableType.ts, 22, 33)) +>fields : Symbol(fields, Decl(substitutionTypeNoMergeOfAssignableType.ts, 22, 41)) +>id : Symbol(id, Decl(substitutionTypeNoMergeOfAssignableType.ts, 22, 51)) + + myTest.test +>myTest.test : Symbol(test, Decl(substitutionTypeNoMergeOfAssignableType.ts, 22, 33)) +>myTest : Symbol(myTest, Decl(substitutionTypeNoMergeOfAssignableType.ts, 22, 6)) +>test : Symbol(test, Decl(substitutionTypeNoMergeOfAssignableType.ts, 22, 33)) + diff --git a/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.types b/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.types new file mode 100644 index 0000000000000..af1f239850c03 --- /dev/null +++ b/tests/baselines/reference/substitutionTypeNoMergeOfAssignableType.types @@ -0,0 +1,52 @@ +=== tests/cases/compiler/substitutionTypeNoMergeOfAssignableType.ts === +interface Entry { + comment?: string; +>comment : string + } + + interface Entity { + fields: {[key: string]: Entry}; +>fields : { [key: string]: Entry; } +>key : string + } + + type Fields = { +>Fields : Fields + + [P in keyof E["fields"]]: E["fields"][P] + }; + + type Nodes = { +>Nodes : Nodes + + [P in keyof T]: T[P] extends Entity + ? Fields + : T[P] + }; + + function makeEntityStore>(config: T): Nodes { +>makeEntityStore : >(config: T) => Nodes +>config : T + + return {} as Nodes +>{} as Nodes : Nodes +>{} : {} + } + + const myTest = makeEntityStore({ test: { fields: { id: {} } } }); +>myTest : Nodes<{ test: { fields: { id: {}; }; }; }> +>makeEntityStore({ test: { fields: { id: {} } } }) : Nodes<{ test: { fields: { id: {}; }; }; }> +>makeEntityStore : >(config: T) => Nodes +>{ test: { fields: { id: {} } } } : { test: { fields: { id: {}; }; }; } +>test : { fields: { id: {}; }; } +>{ fields: { id: {} } } : { fields: { id: {}; }; } +>fields : { id: {}; } +>{ id: {} } : { id: {}; } +>id : {} +>{} : {} + + myTest.test +>myTest.test : Fields<{ fields: { id: {}; }; }> +>myTest : Nodes<{ test: { fields: { id: {}; }; }; }> +>test : Fields<{ fields: { id: {}; }; }> + diff --git a/tests/cases/compiler/substitutionTypeNoMergeOfAssignableType.ts b/tests/cases/compiler/substitutionTypeNoMergeOfAssignableType.ts new file mode 100644 index 0000000000000..b919557d65520 --- /dev/null +++ b/tests/cases/compiler/substitutionTypeNoMergeOfAssignableType.ts @@ -0,0 +1,25 @@ +interface Entry { + comment?: string; + } + + interface Entity { + fields: {[key: string]: Entry}; + } + + type Fields = { + [P in keyof E["fields"]]: E["fields"][P] + }; + + type Nodes = { + [P in keyof T]: T[P] extends Entity + ? Fields + : T[P] + }; + + function makeEntityStore>(config: T): Nodes { + return {} as Nodes + } + + const myTest = makeEntityStore({ test: { fields: { id: {} } } }); + myTest.test + \ No newline at end of file