Merge pull request #26517 from Microsoft/fixMappedArrayTypeConstraint
Fix mapped array type constraint
This commit is contained in:
commit
3e201e7809
|
@ -7119,6 +7119,22 @@ namespace ts {
|
|||
return !!(typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default));
|
||||
}
|
||||
|
||||
function getApparentTypeOfMappedType(type: MappedType) {
|
||||
return type.resolvedApparentType || (type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type));
|
||||
}
|
||||
|
||||
function getResolvedApparentTypeOfMappedType(type: MappedType) {
|
||||
const typeVariable = getHomomorphicTypeVariable(type);
|
||||
if (typeVariable) {
|
||||
const constraint = getConstraintOfTypeParameter(typeVariable);
|
||||
if (constraint && (isArrayType(constraint) || isReadonlyArrayType(constraint) || isTupleType(constraint))) {
|
||||
const mapper = makeUnaryTypeMapper(typeVariable, constraint);
|
||||
return instantiateType(type, combineTypeMappers(mapper, type.mapper));
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a type parameter, return the base constraint of the type parameter. For the string, number,
|
||||
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
|
||||
|
@ -7126,7 +7142,8 @@ namespace ts {
|
|||
*/
|
||||
function getApparentType(type: Type): Type {
|
||||
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || emptyObjectType : type;
|
||||
return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
|
||||
return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(<MappedType>t) :
|
||||
t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
|
||||
t.flags & TypeFlags.StringLike ? globalStringType :
|
||||
t.flags & TypeFlags.NumberLike ? globalNumberType :
|
||||
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
|
||||
|
@ -10159,8 +10176,19 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function getHomomorphicTypeVariable(type: MappedType) {
|
||||
const constraintType = getConstraintTypeFromMappedType(type);
|
||||
if (constraintType.flags & TypeFlags.Index) {
|
||||
const typeVariable = (<IndexType>constraintType).type;
|
||||
if (typeVariable.flags & TypeFlags.TypeParameter) {
|
||||
return <TypeParameter>typeVariable;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function instantiateMappedType(type: MappedType, mapper: TypeMapper): Type {
|
||||
// For a momomorphic mapped type { [P in keyof T]: X }, where T is some type variable, the mapping
|
||||
// For a homomorphic mapped type { [P in keyof T]: X }, where T is some type variable, the mapping
|
||||
// operation depends on T as follows:
|
||||
// * If T is a primitive type no mapping is performed and the result is simply T.
|
||||
// * If T is a union type we distribute the mapped type over the union.
|
||||
|
@ -10170,32 +10198,25 @@ namespace ts {
|
|||
// For example, when T is instantiated to a union type A | B, we produce { [P in keyof A]: X } |
|
||||
// { [P in keyof B]: X }, and when when T is instantiated to a union type A | undefined, we produce
|
||||
// { [P in keyof A]: X } | undefined.
|
||||
const constraintType = getConstraintTypeFromMappedType(type);
|
||||
if (constraintType.flags & TypeFlags.Index) {
|
||||
const typeVariable = (<IndexType>constraintType).type;
|
||||
if (typeVariable.flags & TypeFlags.TypeParameter) {
|
||||
const mappedTypeVariable = instantiateType(typeVariable, mapper);
|
||||
if (typeVariable !== mappedTypeVariable) {
|
||||
return mapType(mappedTypeVariable, t => {
|
||||
if (isMappableType(t)) {
|
||||
const replacementMapper = createReplacementMapper(typeVariable, t, mapper);
|
||||
return isArrayType(t) ? createArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) :
|
||||
isReadonlyArrayType(t) ? createReadonlyArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) :
|
||||
isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
|
||||
instantiateAnonymousType(type, replacementMapper);
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
const typeVariable = getHomomorphicTypeVariable(type);
|
||||
if (typeVariable) {
|
||||
const mappedTypeVariable = instantiateType(typeVariable, mapper);
|
||||
if (typeVariable !== mappedTypeVariable) {
|
||||
return mapType(mappedTypeVariable, t => {
|
||||
if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType) {
|
||||
const replacementMapper = createReplacementMapper(typeVariable, t, mapper);
|
||||
return isArrayType(t) ? createArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) :
|
||||
isReadonlyArrayType(t) ? createReadonlyArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) :
|
||||
isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
|
||||
instantiateAnonymousType(type, replacementMapper);
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
}
|
||||
return instantiateAnonymousType(type, mapper);
|
||||
}
|
||||
|
||||
function isMappableType(type: Type) {
|
||||
return type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection);
|
||||
}
|
||||
|
||||
function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) {
|
||||
const minLength = tupleType.target.minLength;
|
||||
const elementTypes = map(tupleType.typeArguments || emptyArray, (_, i) =>
|
||||
|
@ -11623,7 +11644,6 @@ namespace ts {
|
|||
const constraint = getConstraintForRelation(target);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, constraint, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -11642,7 +11662,6 @@ namespace ts {
|
|||
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(target));
|
||||
const templateType = getTemplateTypeFromMappedType(target);
|
||||
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -11716,6 +11735,23 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
else {
|
||||
// An empty object type is related to any mapped type that includes a '?' modifier.
|
||||
if (isPartialMappedType(target) && !isGenericMappedType(source) && isEmptyObjectType(source)) {
|
||||
return Ternary.True;
|
||||
}
|
||||
if (isGenericMappedType(target)) {
|
||||
if (isGenericMappedType(source)) {
|
||||
if (result = mappedTypeRelatedTo(source, target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
const sourceIsPrimitive = !!(source.flags & TypeFlags.Primitive);
|
||||
if (relation !== identityRelation) {
|
||||
source = getApparentType(source);
|
||||
}
|
||||
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target &&
|
||||
!(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) {
|
||||
// We have type references to the same generic type, and the type references are not marker
|
||||
|
@ -11751,34 +11787,21 @@ namespace ts {
|
|||
}
|
||||
// Even if relationship doesn't hold for unions, intersections, or generic type references,
|
||||
// it may hold in a structural comparison.
|
||||
const sourceIsPrimitive = !!(source.flags & TypeFlags.Primitive);
|
||||
if (relation !== identityRelation) {
|
||||
source = getApparentType(source);
|
||||
}
|
||||
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
|
||||
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally
|
||||
// relates to X. Thus, we include intersection types on the source side here.
|
||||
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) {
|
||||
// Report structural errors only if we haven't reported any errors yet
|
||||
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !sourceIsPrimitive;
|
||||
// An empty object type is related to any mapped type that includes a '?' modifier.
|
||||
if (isPartialMappedType(target) && !isGenericMappedType(source) && isEmptyObjectType(source)) {
|
||||
result = Ternary.True;
|
||||
}
|
||||
else if (isGenericMappedType(target)) {
|
||||
result = isGenericMappedType(source) ? mappedTypeRelatedTo(source, target, reportStructuralErrors) : Ternary.False;
|
||||
}
|
||||
else {
|
||||
result = propertiesRelatedTo(source, target, reportStructuralErrors);
|
||||
result = propertiesRelatedTo(source, target, reportStructuralErrors);
|
||||
if (result) {
|
||||
result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportStructuralErrors);
|
||||
if (result) {
|
||||
result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportStructuralErrors);
|
||||
result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportStructuralErrors);
|
||||
if (result) {
|
||||
result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportStructuralErrors);
|
||||
result &= indexTypesRelatedTo(source, target, IndexKind.String, sourceIsPrimitive, reportStructuralErrors);
|
||||
if (result) {
|
||||
result &= indexTypesRelatedTo(source, target, IndexKind.String, sourceIsPrimitive, reportStructuralErrors);
|
||||
if (result) {
|
||||
result &= indexTypesRelatedTo(source, target, IndexKind.Number, sourceIsPrimitive, reportStructuralErrors);
|
||||
}
|
||||
result &= indexTypesRelatedTo(source, target, IndexKind.Number, sourceIsPrimitive, reportStructuralErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3949,6 +3949,7 @@ namespace ts {
|
|||
constraintType?: Type;
|
||||
templateType?: Type;
|
||||
modifiersType?: Type;
|
||||
resolvedApparentType?: Type;
|
||||
}
|
||||
|
||||
export interface EvolvingArrayType extends ObjectType {
|
||||
|
|
|
@ -61,6 +61,28 @@ function f1(a: number, b: Promise<number>, c: string[], d: Promise<string[]>) {
|
|||
let x3 = all(a, b, c);
|
||||
let x4 = all(a, b, c, d);
|
||||
}
|
||||
|
||||
function f2<T extends any[]>(a: Boxified<T>) {
|
||||
let x: Box<any> | undefined = a.pop();
|
||||
let y: Box<any>[] = a.concat(a);
|
||||
}
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
type ElementType<T> = T extends Array<infer U> ? U : never;
|
||||
type Mapped<T> = { [K in keyof T]: T[K] };
|
||||
|
||||
type F<T> = ElementType<Mapped<T>>;
|
||||
type R1 = F<[string, number, boolean]>; // string | number | boolean
|
||||
type R2 = ElementType<Mapped<[string, number, boolean]>>; // string | number | boolean
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
declare function acceptArray(arr: any[]): void;
|
||||
declare function mapArray<T extends any[]>(arr: T): Mapped<T>;
|
||||
function acceptMappedArray<T extends any[]>(arr: T) {
|
||||
acceptArray(mapArray(arr));
|
||||
}
|
||||
|
||||
|
||||
//// [mappedTypesArraysTuples.js]
|
||||
|
@ -77,6 +99,13 @@ function f1(a, b, c, d) {
|
|||
var x3 = all(a, b, c);
|
||||
var x4 = all(a, b, c, d);
|
||||
}
|
||||
function f2(a) {
|
||||
var x = a.pop();
|
||||
var y = a.concat(a);
|
||||
}
|
||||
function acceptMappedArray(arr) {
|
||||
acceptArray(mapArray(arr));
|
||||
}
|
||||
|
||||
|
||||
//// [mappedTypesArraysTuples.d.ts]
|
||||
|
@ -142,3 +171,14 @@ declare type Awaitified<T> = {
|
|||
};
|
||||
declare function all<T extends any[]>(...values: T): Promise<Awaitified<T>>;
|
||||
declare function f1(a: number, b: Promise<number>, c: string[], d: Promise<string[]>): void;
|
||||
declare function f2<T extends any[]>(a: Boxified<T>): void;
|
||||
declare type ElementType<T> = T extends Array<infer U> ? U : never;
|
||||
declare type Mapped<T> = {
|
||||
[K in keyof T]: T[K];
|
||||
};
|
||||
declare type F<T> = ElementType<Mapped<T>>;
|
||||
declare type R1 = F<[string, number, boolean]>;
|
||||
declare type R2 = ElementType<Mapped<[string, number, boolean]>>;
|
||||
declare function acceptArray(arr: any[]): void;
|
||||
declare function mapArray<T extends any[]>(arr: T): Mapped<T>;
|
||||
declare function acceptMappedArray<T extends any[]>(arr: T): void;
|
||||
|
|
|
@ -245,3 +245,86 @@ function f1(a: number, b: Promise<number>, c: string[], d: Promise<string[]>) {
|
|||
>d : Symbol(d, Decl(mappedTypesArraysTuples.ts, 56, 55))
|
||||
}
|
||||
|
||||
function f2<T extends any[]>(a: Boxified<T>) {
|
||||
>f2 : Symbol(f2, Decl(mappedTypesArraysTuples.ts, 61, 1))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 63, 12))
|
||||
>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 63, 29))
|
||||
>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 63, 12))
|
||||
|
||||
let x: Box<any> | undefined = a.pop();
|
||||
>x : Symbol(x, Decl(mappedTypesArraysTuples.ts, 64, 7))
|
||||
>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0))
|
||||
>a.pop : Symbol(Array.pop, Decl(lib.es5.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 63, 29))
|
||||
>pop : Symbol(Array.pop, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
let y: Box<any>[] = a.concat(a);
|
||||
>y : Symbol(y, Decl(mappedTypesArraysTuples.ts, 65, 7))
|
||||
>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0))
|
||||
>a.concat : Symbol(Array.concat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 63, 29))
|
||||
>concat : Symbol(Array.concat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 63, 29))
|
||||
}
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
type ElementType<T> = T extends Array<infer U> ? U : never;
|
||||
>ElementType : Symbol(ElementType, Decl(mappedTypesArraysTuples.ts, 66, 1))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 70, 17))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 70, 17))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>U : Symbol(U, Decl(mappedTypesArraysTuples.ts, 70, 43))
|
||||
>U : Symbol(U, Decl(mappedTypesArraysTuples.ts, 70, 43))
|
||||
|
||||
type Mapped<T> = { [K in keyof T]: T[K] };
|
||||
>Mapped : Symbol(Mapped, Decl(mappedTypesArraysTuples.ts, 70, 59))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 71, 12))
|
||||
>K : Symbol(K, Decl(mappedTypesArraysTuples.ts, 71, 20))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 71, 12))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 71, 12))
|
||||
>K : Symbol(K, Decl(mappedTypesArraysTuples.ts, 71, 20))
|
||||
|
||||
type F<T> = ElementType<Mapped<T>>;
|
||||
>F : Symbol(F, Decl(mappedTypesArraysTuples.ts, 71, 42))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 73, 7))
|
||||
>ElementType : Symbol(ElementType, Decl(mappedTypesArraysTuples.ts, 66, 1))
|
||||
>Mapped : Symbol(Mapped, Decl(mappedTypesArraysTuples.ts, 70, 59))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 73, 7))
|
||||
|
||||
type R1 = F<[string, number, boolean]>; // string | number | boolean
|
||||
>R1 : Symbol(R1, Decl(mappedTypesArraysTuples.ts, 73, 35))
|
||||
>F : Symbol(F, Decl(mappedTypesArraysTuples.ts, 71, 42))
|
||||
|
||||
type R2 = ElementType<Mapped<[string, number, boolean]>>; // string | number | boolean
|
||||
>R2 : Symbol(R2, Decl(mappedTypesArraysTuples.ts, 74, 39))
|
||||
>ElementType : Symbol(ElementType, Decl(mappedTypesArraysTuples.ts, 66, 1))
|
||||
>Mapped : Symbol(Mapped, Decl(mappedTypesArraysTuples.ts, 70, 59))
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
declare function acceptArray(arr: any[]): void;
|
||||
>acceptArray : Symbol(acceptArray, Decl(mappedTypesArraysTuples.ts, 75, 57))
|
||||
>arr : Symbol(arr, Decl(mappedTypesArraysTuples.ts, 79, 29))
|
||||
|
||||
declare function mapArray<T extends any[]>(arr: T): Mapped<T>;
|
||||
>mapArray : Symbol(mapArray, Decl(mappedTypesArraysTuples.ts, 79, 47))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 80, 26))
|
||||
>arr : Symbol(arr, Decl(mappedTypesArraysTuples.ts, 80, 43))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 80, 26))
|
||||
>Mapped : Symbol(Mapped, Decl(mappedTypesArraysTuples.ts, 70, 59))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 80, 26))
|
||||
|
||||
function acceptMappedArray<T extends any[]>(arr: T) {
|
||||
>acceptMappedArray : Symbol(acceptMappedArray, Decl(mappedTypesArraysTuples.ts, 80, 62))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 81, 27))
|
||||
>arr : Symbol(arr, Decl(mappedTypesArraysTuples.ts, 81, 44))
|
||||
>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 81, 27))
|
||||
|
||||
acceptArray(mapArray(arr));
|
||||
>acceptArray : Symbol(acceptArray, Decl(mappedTypesArraysTuples.ts, 75, 57))
|
||||
>mapArray : Symbol(mapArray, Decl(mappedTypesArraysTuples.ts, 79, 47))
|
||||
>arr : Symbol(arr, Decl(mappedTypesArraysTuples.ts, 81, 44))
|
||||
}
|
||||
|
||||
|
|
|
@ -182,3 +182,62 @@ function f1(a: number, b: Promise<number>, c: string[], d: Promise<string[]>) {
|
|||
>d : Promise<string[]>
|
||||
}
|
||||
|
||||
function f2<T extends any[]>(a: Boxified<T>) {
|
||||
>f2 : <T extends any[]>(a: Boxified<T>) => void
|
||||
>a : Boxified<T>
|
||||
|
||||
let x: Box<any> | undefined = a.pop();
|
||||
>x : Box<any> | undefined
|
||||
>a.pop() : Box<any> | undefined
|
||||
>a.pop : () => Box<any> | undefined
|
||||
>a : Boxified<T>
|
||||
>pop : () => Box<any> | undefined
|
||||
|
||||
let y: Box<any>[] = a.concat(a);
|
||||
>y : Box<any>[]
|
||||
>a.concat(a) : Box<any>[]
|
||||
>a.concat : { (...items: ConcatArray<Box<any>>[]): Box<any>[]; (...items: (Box<any> | ConcatArray<Box<any>>)[]): Box<any>[]; }
|
||||
>a : Boxified<T>
|
||||
>concat : { (...items: ConcatArray<Box<any>>[]): Box<any>[]; (...items: (Box<any> | ConcatArray<Box<any>>)[]): Box<any>[]; }
|
||||
>a : Boxified<T>
|
||||
}
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
type ElementType<T> = T extends Array<infer U> ? U : never;
|
||||
>ElementType : ElementType<T>
|
||||
|
||||
type Mapped<T> = { [K in keyof T]: T[K] };
|
||||
>Mapped : Mapped<T>
|
||||
|
||||
type F<T> = ElementType<Mapped<T>>;
|
||||
>F : ElementType<Mapped<T>>
|
||||
|
||||
type R1 = F<[string, number, boolean]>; // string | number | boolean
|
||||
>R1 : string | number | boolean
|
||||
|
||||
type R2 = ElementType<Mapped<[string, number, boolean]>>; // string | number | boolean
|
||||
>R2 : string | number | boolean
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
declare function acceptArray(arr: any[]): void;
|
||||
>acceptArray : (arr: any[]) => void
|
||||
>arr : any[]
|
||||
|
||||
declare function mapArray<T extends any[]>(arr: T): Mapped<T>;
|
||||
>mapArray : <T extends any[]>(arr: T) => Mapped<T>
|
||||
>arr : T
|
||||
|
||||
function acceptMappedArray<T extends any[]>(arr: T) {
|
||||
>acceptMappedArray : <T extends any[]>(arr: T) => void
|
||||
>arr : T
|
||||
|
||||
acceptArray(mapArray(arr));
|
||||
>acceptArray(mapArray(arr)) : void
|
||||
>acceptArray : (arr: any[]) => void
|
||||
>mapArray(arr) : Mapped<T>
|
||||
>mapArray : <T extends any[]>(arr: T) => Mapped<T>
|
||||
>arr : T
|
||||
}
|
||||
|
||||
|
|
|
@ -63,3 +63,25 @@ function f1(a: number, b: Promise<number>, c: string[], d: Promise<string[]>) {
|
|||
let x3 = all(a, b, c);
|
||||
let x4 = all(a, b, c, d);
|
||||
}
|
||||
|
||||
function f2<T extends any[]>(a: Boxified<T>) {
|
||||
let x: Box<any> | undefined = a.pop();
|
||||
let y: Box<any>[] = a.concat(a);
|
||||
}
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
type ElementType<T> = T extends Array<infer U> ? U : never;
|
||||
type Mapped<T> = { [K in keyof T]: T[K] };
|
||||
|
||||
type F<T> = ElementType<Mapped<T>>;
|
||||
type R1 = F<[string, number, boolean]>; // string | number | boolean
|
||||
type R2 = ElementType<Mapped<[string, number, boolean]>>; // string | number | boolean
|
||||
|
||||
// Repro from #26163
|
||||
|
||||
declare function acceptArray(arr: any[]): void;
|
||||
declare function mapArray<T extends any[]>(arr: T): Mapped<T>;
|
||||
function acceptMappedArray<T extends any[]>(arr: T) {
|
||||
acceptArray(mapArray(arr));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue