Skip to content

Commit

Permalink
Fixed cache key computation for tuple target types with partially nam…
Browse files Browse the repository at this point in the history
…ed members (microsoft#55695)
  • Loading branch information
Andarist authored Sep 11, 2023
1 parent 4f899a1 commit 4b0f54f
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 2 deletions.
3 changes: 1 addition & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16392,10 +16392,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// [...X[]] is equivalent to just X[]
return readonly ? globalReadonlyArrayType : globalArrayType;
}
const memberIds = mapDefined(namedMemberDeclarations, node => node ? getNodeId(node) : undefined);
const key = map(elementFlags, f => f & ElementFlags.Required ? "#" : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*").join() +
(readonly ? "R" : "") +
(memberIds.length ? "," + memberIds.join(",") : "");
(some(namedMemberDeclarations, node => !!node) ? "," + map(namedMemberDeclarations, node => node ? getNodeId(node) : "_").join(",") : "");
let type = tupleTypes.get(key);
if (!type) {
tupleTypes.set(key, type = createTupleTargetType(elementFlags, readonly, namedMemberDeclarations));
Expand Down
32 changes: 32 additions & 0 deletions tests/baselines/reference/partiallyNamedTuples2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//// [tests/cases/conformance/types/tuple/named/partiallyNamedTuples2.ts] ////

//// [partiallyNamedTuples2.ts]
// https://github.com/microsoft/TypeScript/issues/55693
interface MultiKeyMap<Keys extends readonly unknown[], Value> {
get<Key extends GetKeys<Keys>>(...key: Key): GetResult<Keys, Key, Value>;
}
type GetKeys<Keys extends readonly unknown[]> = Keys extends [
...infer Remain,
infer _,
]
? Keys | GetKeys<Remain>
: Keys;
type GetResult<
Id extends readonly unknown[],
Args extends GetKeys<Id>,
Value,
> = Args extends Id
? Value | undefined
: Id extends [...Args, ...infer Rest]
? Iterable<[...Rest, Value]>
: never;
const x: MultiKeyMap<[id1: string, id2: string], object> = null!;
const id1 = "abc" as string;
const matches = x.get(id1);


//// [partiallyNamedTuples2.js]
"use strict";
var x = null;
var id1 = "abc";
var matches = x.get(id1);
87 changes: 87 additions & 0 deletions tests/baselines/reference/partiallyNamedTuples2.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//// [tests/cases/conformance/types/tuple/named/partiallyNamedTuples2.ts] ////

=== partiallyNamedTuples2.ts ===
// https://github.com/microsoft/TypeScript/issues/55693
interface MultiKeyMap<Keys extends readonly unknown[], Value> {
>MultiKeyMap : Symbol(MultiKeyMap, Decl(partiallyNamedTuples2.ts, 0, 0))
>Keys : Symbol(Keys, Decl(partiallyNamedTuples2.ts, 1, 22))
>Value : Symbol(Value, Decl(partiallyNamedTuples2.ts, 1, 54))

get<Key extends GetKeys<Keys>>(...key: Key): GetResult<Keys, Key, Value>;
>get : Symbol(MultiKeyMap.get, Decl(partiallyNamedTuples2.ts, 1, 63))
>Key : Symbol(Key, Decl(partiallyNamedTuples2.ts, 2, 6))
>GetKeys : Symbol(GetKeys, Decl(partiallyNamedTuples2.ts, 3, 1))
>Keys : Symbol(Keys, Decl(partiallyNamedTuples2.ts, 1, 22))
>key : Symbol(key, Decl(partiallyNamedTuples2.ts, 2, 33))
>Key : Symbol(Key, Decl(partiallyNamedTuples2.ts, 2, 6))
>GetResult : Symbol(GetResult, Decl(partiallyNamedTuples2.ts, 9, 9))
>Keys : Symbol(Keys, Decl(partiallyNamedTuples2.ts, 1, 22))
>Key : Symbol(Key, Decl(partiallyNamedTuples2.ts, 2, 6))
>Value : Symbol(Value, Decl(partiallyNamedTuples2.ts, 1, 54))
}
type GetKeys<Keys extends readonly unknown[]> = Keys extends [
>GetKeys : Symbol(GetKeys, Decl(partiallyNamedTuples2.ts, 3, 1))
>Keys : Symbol(Keys, Decl(partiallyNamedTuples2.ts, 4, 13))
>Keys : Symbol(Keys, Decl(partiallyNamedTuples2.ts, 4, 13))

...infer Remain,
>Remain : Symbol(Remain, Decl(partiallyNamedTuples2.ts, 5, 10))

infer _,
>_ : Symbol(_, Decl(partiallyNamedTuples2.ts, 6, 7))

]
? Keys | GetKeys<Remain>
>Keys : Symbol(Keys, Decl(partiallyNamedTuples2.ts, 4, 13))
>GetKeys : Symbol(GetKeys, Decl(partiallyNamedTuples2.ts, 3, 1))
>Remain : Symbol(Remain, Decl(partiallyNamedTuples2.ts, 5, 10))

: Keys;
>Keys : Symbol(Keys, Decl(partiallyNamedTuples2.ts, 4, 13))

type GetResult<
>GetResult : Symbol(GetResult, Decl(partiallyNamedTuples2.ts, 9, 9))

Id extends readonly unknown[],
>Id : Symbol(Id, Decl(partiallyNamedTuples2.ts, 10, 15))

Args extends GetKeys<Id>,
>Args : Symbol(Args, Decl(partiallyNamedTuples2.ts, 11, 32))
>GetKeys : Symbol(GetKeys, Decl(partiallyNamedTuples2.ts, 3, 1))
>Id : Symbol(Id, Decl(partiallyNamedTuples2.ts, 10, 15))

Value,
>Value : Symbol(Value, Decl(partiallyNamedTuples2.ts, 12, 27))

> = Args extends Id
>Args : Symbol(Args, Decl(partiallyNamedTuples2.ts, 11, 32))
>Id : Symbol(Id, Decl(partiallyNamedTuples2.ts, 10, 15))

? Value | undefined
>Value : Symbol(Value, Decl(partiallyNamedTuples2.ts, 12, 27))

: Id extends [...Args, ...infer Rest]
>Id : Symbol(Id, Decl(partiallyNamedTuples2.ts, 10, 15))
>Args : Symbol(Args, Decl(partiallyNamedTuples2.ts, 11, 32))
>Rest : Symbol(Rest, Decl(partiallyNamedTuples2.ts, 16, 33))

? Iterable<[...Rest, Value]>
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
>Rest : Symbol(Rest, Decl(partiallyNamedTuples2.ts, 16, 33))
>Value : Symbol(Value, Decl(partiallyNamedTuples2.ts, 12, 27))

: never;
const x: MultiKeyMap<[id1: string, id2: string], object> = null!;
>x : Symbol(x, Decl(partiallyNamedTuples2.ts, 19, 5))
>MultiKeyMap : Symbol(MultiKeyMap, Decl(partiallyNamedTuples2.ts, 0, 0))

const id1 = "abc" as string;
>id1 : Symbol(id1, Decl(partiallyNamedTuples2.ts, 20, 5))

const matches = x.get(id1);
>matches : Symbol(matches, Decl(partiallyNamedTuples2.ts, 21, 5))
>x.get : Symbol(MultiKeyMap.get, Decl(partiallyNamedTuples2.ts, 1, 63))
>x : Symbol(x, Decl(partiallyNamedTuples2.ts, 19, 5))
>get : Symbol(MultiKeyMap.get, Decl(partiallyNamedTuples2.ts, 1, 63))
>id1 : Symbol(id1, Decl(partiallyNamedTuples2.ts, 20, 5))

45 changes: 45 additions & 0 deletions tests/baselines/reference/partiallyNamedTuples2.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//// [tests/cases/conformance/types/tuple/named/partiallyNamedTuples2.ts] ////

=== partiallyNamedTuples2.ts ===
// https://github.com/microsoft/TypeScript/issues/55693
interface MultiKeyMap<Keys extends readonly unknown[], Value> {
get<Key extends GetKeys<Keys>>(...key: Key): GetResult<Keys, Key, Value>;
>get : <Key extends GetKeys<Keys>>(...key: Key) => GetResult<Keys, Key, Value>
>key : Key
}
type GetKeys<Keys extends readonly unknown[]> = Keys extends [
>GetKeys : GetKeys<Keys>

...infer Remain,
infer _,
]
? Keys | GetKeys<Remain>
: Keys;
type GetResult<
>GetResult : GetResult<Id, Args, Value>

Id extends readonly unknown[],
Args extends GetKeys<Id>,
Value,
> = Args extends Id
? Value | undefined
: Id extends [...Args, ...infer Rest]
? Iterable<[...Rest, Value]>
: never;
const x: MultiKeyMap<[id1: string, id2: string], object> = null!;
>x : MultiKeyMap<[id1: string, id2: string], object>
>null! : never

const id1 = "abc" as string;
>id1 : string
>"abc" as string : string
>"abc" : "abc"

const matches = x.get(id1);
>matches : Iterable<[id2: string, object]>
>x.get(id1) : Iterable<[id2: string, object]>
>x.get : <Key extends [id1: string, id2: string] | [id1: string] | []>(...key: Key) => GetResult<[id1: string, id2: string], Key, object>
>x : MultiKeyMap<[id1: string, id2: string], object>
>get : <Key extends [id1: string, id2: string] | [id1: string] | []>(...key: Key) => GetResult<[id1: string, id2: string], Key, object>
>id1 : string

25 changes: 25 additions & 0 deletions tests/cases/conformance/types/tuple/named/partiallyNamedTuples2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// @strict: true
// @lib: esnext

// https://github.com/microsoft/TypeScript/issues/55693
interface MultiKeyMap<Keys extends readonly unknown[], Value> {
get<Key extends GetKeys<Keys>>(...key: Key): GetResult<Keys, Key, Value>;
}
type GetKeys<Keys extends readonly unknown[]> = Keys extends [
...infer Remain,
infer _,
]
? Keys | GetKeys<Remain>
: Keys;
type GetResult<
Id extends readonly unknown[],
Args extends GetKeys<Id>,
Value,
> = Args extends Id
? Value | undefined
: Id extends [...Args, ...infer Rest]
? Iterable<[...Rest, Value]>
: never;
const x: MultiKeyMap<[id1: string, id2: string], object> = null!;
const id1 = "abc" as string;
const matches = x.get(id1);

0 comments on commit 4b0f54f

Please sign in to comment.