Support partial reverse mapped inferences with tuple types (#41106)

* Support partial reverse mapped inferences with tuple types

* Add tests

* Accept new baselines
This commit is contained in:
Anders Hejlsberg
2020-10-22 11:27:41 -07:00
committed by GitHub
parent 97083ea6a2
commit d1f87d18b1
6 changed files with 304 additions and 1 deletions

View File

@@ -19709,7 +19709,8 @@ namespace ts {
// arrow function, but is considered partially inferable because property 'a' has an inferable type.
function isPartiallyInferableType(type: Type): boolean {
return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) ||
isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop)));
isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) ||
isTupleType(type) && some(getTypeArguments(type), isPartiallyInferableType);
}
function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) {

View File

@@ -98,4 +98,36 @@ tests/cases/compiler/reverseMappedPartiallyInferableTypes.ts(91,20): error TS257
}
}
});
// Repros from #40809
type Mapped1<T> = {
[K in keyof T]: [T[K], (arg: T) => boolean];
};
declare function inferMapped1<T>(arg: Mapped1<T>): void;
inferMapped1({
key: [3, arg => arg.key > 5]
});
type Mapped2<T> = {
[K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean];
};
declare function inferMapped2<T>(arg: Mapped2<T>): void;
inferMapped2({
key: [3, arg => arg.key > 5]
});
type MappedReadonly<T> = {
readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean];
};
declare function inferMappedReadonly<T>(arg: MappedReadonly<T>): void;
inferMappedReadonly({
key: [3, arg => arg.key > 5]
});

View File

@@ -93,6 +93,38 @@ const obj3 = id({
}
}
});
// Repros from #40809
type Mapped1<T> = {
[K in keyof T]: [T[K], (arg: T) => boolean];
};
declare function inferMapped1<T>(arg: Mapped1<T>): void;
inferMapped1({
key: [3, arg => arg.key > 5]
});
type Mapped2<T> = {
[K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean];
};
declare function inferMapped2<T>(arg: Mapped2<T>): void;
inferMapped2({
key: [3, arg => arg.key > 5]
});
type MappedReadonly<T> = {
readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean];
};
declare function inferMappedReadonly<T>(arg: MappedReadonly<T>): void;
inferMappedReadonly({
key: [3, arg => arg.key > 5]
});
//// [reverseMappedPartiallyInferableTypes.js]
@@ -142,3 +174,12 @@ var obj3 = id({
}
}
});
inferMapped1({
key: [3, function (arg) { return arg.key > 5; }]
});
inferMapped2({
key: [3, function (arg) { return arg.key > 5; }]
});
inferMappedReadonly({
key: [3, function (arg) { return arg.key > 5; }]
});

View File

@@ -257,3 +257,105 @@ const obj3 = id({
}
});
// Repros from #40809
type Mapped1<T> = {
>Mapped1 : Symbol(Mapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 93, 3))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13))
[K in keyof T]: [T[K], (arg: T) => boolean];
>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 98, 5))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13))
>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 98, 5))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 98, 28))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 97, 13))
};
declare function inferMapped1<T>(arg: Mapped1<T>): void;
>inferMapped1 : Symbol(inferMapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 99, 2))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 101, 30))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 101, 33))
>Mapped1 : Symbol(Mapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 93, 3))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 101, 30))
inferMapped1({
>inferMapped1 : Symbol(inferMapped1, Decl(reverseMappedPartiallyInferableTypes.ts, 99, 2))
key: [3, arg => arg.key > 5]
>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 103, 14))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 104, 12))
>arg.key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 103, 14))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 104, 12))
>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 103, 14))
});
type Mapped2<T> = {
>Mapped2 : Symbol(Mapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 105, 3))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13))
[K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean];
>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 108, 5))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13))
>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 108, 5))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 108, 58))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 107, 13))
};
declare function inferMapped2<T>(arg: Mapped2<T>): void;
>inferMapped2 : Symbol(inferMapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 109, 2))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 111, 30))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 111, 33))
>Mapped2 : Symbol(Mapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 105, 3))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 111, 30))
inferMapped2({
>inferMapped2 : Symbol(inferMapped2, Decl(reverseMappedPartiallyInferableTypes.ts, 109, 2))
key: [3, arg => arg.key > 5]
>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 113, 14))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 114, 12))
>arg.key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 113, 14))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 114, 12))
>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 113, 14))
});
type MappedReadonly<T> = {
>MappedReadonly : Symbol(MappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 115, 3))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20))
readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean];
>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 118, 14))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20))
>K : Symbol(K, Decl(reverseMappedPartiallyInferableTypes.ts, 118, 14))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 118, 46))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 117, 20))
};
declare function inferMappedReadonly<T>(arg: MappedReadonly<T>): void;
>inferMappedReadonly : Symbol(inferMappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 119, 2))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 121, 37))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 121, 40))
>MappedReadonly : Symbol(MappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 115, 3))
>T : Symbol(T, Decl(reverseMappedPartiallyInferableTypes.ts, 121, 37))
inferMappedReadonly({
>inferMappedReadonly : Symbol(inferMappedReadonly, Decl(reverseMappedPartiallyInferableTypes.ts, 119, 2))
key: [3, arg => arg.key > 5]
>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 123, 21))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 124, 12))
>arg.key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 123, 21))
>arg : Symbol(arg, Decl(reverseMappedPartiallyInferableTypes.ts, 124, 12))
>key : Symbol(key, Decl(reverseMappedPartiallyInferableTypes.ts, 123, 21))
});

View File

@@ -229,3 +229,98 @@ const obj3 = id({
}
});
// Repros from #40809
type Mapped1<T> = {
>Mapped1 : Mapped1<T>
[K in keyof T]: [T[K], (arg: T) => boolean];
>arg : T
};
declare function inferMapped1<T>(arg: Mapped1<T>): void;
>inferMapped1 : <T>(arg: Mapped1<T>) => void
>arg : Mapped1<T>
inferMapped1({
>inferMapped1({ key: [3, arg => arg.key > 5]}) : void
>inferMapped1 : <T>(arg: Mapped1<T>) => void
>{ key: [3, arg => arg.key > 5]} : { key: [number, (arg: { key: number; }) => boolean]; }
key: [3, arg => arg.key > 5]
>key : [number, (arg: { key: number; }) => boolean]
>[3, arg => arg.key > 5] : [number, (arg: { key: number; }) => boolean]
>3 : 3
>arg => arg.key > 5 : (arg: { key: number; }) => boolean
>arg : { key: number; }
>arg.key > 5 : boolean
>arg.key : number
>arg : { key: number; }
>key : number
>5 : 5
});
type Mapped2<T> = {
>Mapped2 : Mapped2<T>
[K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean];
>arg : T
};
declare function inferMapped2<T>(arg: Mapped2<T>): void;
>inferMapped2 : <T>(arg: Mapped2<T>) => void
>arg : Mapped2<T>
inferMapped2({
>inferMapped2({ key: [3, arg => arg.key > 5]}) : void
>inferMapped2 : <T>(arg: Mapped2<T>) => void
>{ key: [3, arg => arg.key > 5]} : { key: [number, (arg: { key: number; }) => boolean]; }
key: [3, arg => arg.key > 5]
>key : [number, (arg: { key: number; }) => boolean]
>[3, arg => arg.key > 5] : [number, (arg: { key: number; }) => boolean]
>3 : 3
>arg => arg.key > 5 : (arg: { key: number; }) => boolean
>arg : { key: number; }
>arg.key > 5 : boolean
>arg.key : number
>arg : { key: number; }
>key : number
>5 : 5
});
type MappedReadonly<T> = {
>MappedReadonly : MappedReadonly<T>
readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean];
>arg : T
};
declare function inferMappedReadonly<T>(arg: MappedReadonly<T>): void;
>inferMappedReadonly : <T>(arg: MappedReadonly<T>) => void
>arg : MappedReadonly<T>
inferMappedReadonly({
>inferMappedReadonly({ key: [3, arg => arg.key > 5]}) : void
>inferMappedReadonly : <T>(arg: MappedReadonly<T>) => void
>{ key: [3, arg => arg.key > 5]} : { key: [number, (arg: { key: number; }) => boolean]; }
key: [3, arg => arg.key > 5]
>key : [number, (arg: { key: number; }) => boolean]
>[3, arg => arg.key > 5] : [number, (arg: { key: number; }) => boolean]
>3 : 3
>arg => arg.key > 5 : (arg: { key: number; }) => boolean
>arg : { key: number; }
>arg.key > 5 : boolean
>arg.key : number
>arg : { key: number; }
>key : number
>5 : 5
});

View File

@@ -94,3 +94,35 @@ const obj3 = id({
}
}
});
// Repros from #40809
type Mapped1<T> = {
[K in keyof T]: [T[K], (arg: T) => boolean];
};
declare function inferMapped1<T>(arg: Mapped1<T>): void;
inferMapped1({
key: [3, arg => arg.key > 5]
});
type Mapped2<T> = {
[K in keyof T]: [T[K], unknown extends T ? unknown : (arg: T) => boolean];
};
declare function inferMapped2<T>(arg: Mapped2<T>): void;
inferMapped2({
key: [3, arg => arg.key > 5]
});
type MappedReadonly<T> = {
readonly [K in keyof T]: readonly [T[K], (arg: T) => boolean];
};
declare function inferMappedReadonly<T>(arg: MappedReadonly<T>): void;
inferMappedReadonly({
key: [3, arg => arg.key > 5]
});