From 238c341701439a95d5eb71a4cf421c0574d0ee47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 1 Sep 2022 16:28:13 +0200 Subject: [PATCH] Defer distributing index over generic object types (#50540) * Defer distributing index over generic object types * Only check if the index type should be deferred for intersection types * Add an additional test case --- src/compiler/checker.ts | 2 +- ...ithNullableGenericIndexedAccessArg.symbols | 77 +++++++++++++++++++ ...eWithNullableGenericIndexedAccessArg.types | 49 ++++++++++++ ...ableWithNullableGenericIndexedAccessArg.ts | 33 ++++++++ 4 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.symbols create mode 100644 tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.types create mode 100644 tests/cases/compiler/nonNullableWithNullableGenericIndexedAccessArg.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9f4a9f62bfe40..8630974f77f26 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15906,7 +15906,7 @@ namespace ts { // (T | U)[K] -> T[K] | U[K] (reading) // (T | U)[K] -> T[K] & U[K] (writing) // (T & U)[K] -> T[K] & U[K] - if (objectType.flags & TypeFlags.UnionOrIntersection) { + if (objectType.flags & TypeFlags.Union || objectType.flags & TypeFlags.Intersection && !shouldDeferIndexType(objectType)) { const types = map((objectType as UnionOrIntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType), writing)); return objectType.flags & TypeFlags.Intersection || writing ? getIntersectionType(types) : getUnionType(types); } diff --git a/tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.symbols b/tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.symbols new file mode 100644 index 0000000000000..a461d361eedcc --- /dev/null +++ b/tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.symbols @@ -0,0 +1,77 @@ +=== tests/cases/compiler/nonNullableWithNullableGenericIndexedAccessArg.ts === +// repro from #50539 + +interface StateSchema { +>StateSchema : Symbol(StateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 0, 0)) + + states?: { +>states : Symbol(StateSchema.states, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 2, 23)) + + [key: string]: StateSchema; +>key : Symbol(key, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 4, 5)) +>StateSchema : Symbol(StateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 0, 0)) + + }; +} + +declare class StateNode { +>StateNode : Symbol(StateNode, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 6, 1)) +>TStateSchema : Symbol(TStateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 8, 24)) +>StateSchema : Symbol(StateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 0, 0)) + + schema: TStateSchema; +>schema : Symbol(StateNode.schema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 8, 59)) +>TStateSchema : Symbol(TStateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 8, 24)) +} + +type StateNodesConfig = { +>StateNodesConfig : Symbol(StateNodesConfig, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 10, 1)) +>TStateSchema : Symbol(TStateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 12, 22)) +>StateSchema : Symbol(StateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 0, 0)) + + [K in keyof TStateSchema["states"]]: StateNode[K]>; +>K : Symbol(K, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 13, 3)) +>TStateSchema : Symbol(TStateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 12, 22)) +>StateNode : Symbol(StateNode, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 6, 1)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) +>TStateSchema : Symbol(TStateSchema, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 12, 22)) +>K : Symbol(K, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 13, 3)) + +}; + +// repro from #50539#issuecomment-1234067835 + +type Ordering = { +>Ordering : Symbol(Ordering, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 14, 2)) +>TOrderBy : Symbol(TOrderBy, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 18, 14)) + + orderBy: TOrderBy +>orderBy : Symbol(orderBy, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 18, 42)) +>TOrderBy : Symbol(TOrderBy, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 18, 14)) +} + +type Query = { +>Query : Symbol(Query, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 20, 1)) +>TOrderBy : Symbol(TOrderBy, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 22, 11)) + + order?: Ordering +>order : Symbol(order, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 22, 39)) +>Ordering : Symbol(Ordering, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 14, 2)) +>TOrderBy : Symbol(TOrderBy, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 22, 11)) +} + +type QueryHandler< +>QueryHandler : Symbol(QueryHandler, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 24, 1)) + + TQuery extends Query, +>TQuery : Symbol(TQuery, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 26, 18)) +>Query : Symbol(Query, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 20, 1)) +>TOrderBy : Symbol(TOrderBy, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 27, 35)) + + TOrderBy extends string = NonNullable["orderBy"] +>TOrderBy : Symbol(TOrderBy, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 27, 35)) +>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --)) +>TQuery : Symbol(TQuery, Decl(nonNullableWithNullableGenericIndexedAccessArg.ts, 26, 18)) + +> = {} + diff --git a/tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.types b/tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.types new file mode 100644 index 0000000000000..f2bbff47ada4c --- /dev/null +++ b/tests/baselines/reference/nonNullableWithNullableGenericIndexedAccessArg.types @@ -0,0 +1,49 @@ +=== tests/cases/compiler/nonNullableWithNullableGenericIndexedAccessArg.ts === +// repro from #50539 + +interface StateSchema { + states?: { +>states : { [key: string]: StateSchema; } | undefined + + [key: string]: StateSchema; +>key : string + + }; +} + +declare class StateNode { +>StateNode : StateNode + + schema: TStateSchema; +>schema : TStateSchema +} + +type StateNodesConfig = { +>StateNodesConfig : StateNodesConfig + + [K in keyof TStateSchema["states"]]: StateNode[K]>; +}; + +// repro from #50539#issuecomment-1234067835 + +type Ordering = { +>Ordering : Ordering + + orderBy: TOrderBy +>orderBy : TOrderBy +} + +type Query = { +>Query : Query + + order?: Ordering +>order : Ordering | undefined +} + +type QueryHandler< +>QueryHandler : QueryHandler + + TQuery extends Query, + TOrderBy extends string = NonNullable["orderBy"] +> = {} + diff --git a/tests/cases/compiler/nonNullableWithNullableGenericIndexedAccessArg.ts b/tests/cases/compiler/nonNullableWithNullableGenericIndexedAccessArg.ts new file mode 100644 index 0000000000000..8b8d4dc0e24ca --- /dev/null +++ b/tests/cases/compiler/nonNullableWithNullableGenericIndexedAccessArg.ts @@ -0,0 +1,33 @@ +// @noEmit: true +// @strict: true + +// repro from #50539 + +interface StateSchema { + states?: { + [key: string]: StateSchema; + }; +} + +declare class StateNode { + schema: TStateSchema; +} + +type StateNodesConfig = { + [K in keyof TStateSchema["states"]]: StateNode[K]>; +}; + +// repro from #50539#issuecomment-1234067835 + +type Ordering = { + orderBy: TOrderBy +} + +type Query = { + order?: Ordering +} + +type QueryHandler< + TQuery extends Query, + TOrderBy extends string = NonNullable["orderBy"] +> = {}