mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Add fallback logic for generating signatures for unions of array members (#53489)
This commit is contained in:
parent
58f030072e
commit
b0c80207ac
@ -14262,7 +14262,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
* maps primitive types and type parameters are to their apparent types.
|
||||
*/
|
||||
function getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[] {
|
||||
return getSignaturesOfStructuredType(getReducedApparentType(type), kind);
|
||||
const result = getSignaturesOfStructuredType(getReducedApparentType(type), kind);
|
||||
if (kind === SignatureKind.Call && !length(result) && type.flags & TypeFlags.Union) {
|
||||
if ((type as UnionType).arrayFallbackSignatures) {
|
||||
return (type as UnionType).arrayFallbackSignatures!;
|
||||
}
|
||||
// If the union is all different instantiations of a member of the global array type...
|
||||
let memberName: __String;
|
||||
if (everyType(type, t => !!t.symbol?.parent && isArrayOrTupleSymbol(t.symbol.parent) && (!memberName ? (memberName = t.symbol.escapedName, true) : memberName === t.symbol.escapedName))) {
|
||||
// Transform the type from `(A[] | B[])["member"]` to `(A | B)[]["member"]` (since we pretend array is covariant anyway)
|
||||
const arrayArg = mapType(type, t => getMappedType((isReadonlyArraySymbol(t.symbol.parent) ? globalReadonlyArrayType : globalArrayType).typeParameters![0], (t as AnonymousType).mapper!));
|
||||
const arrayType = createArrayType(arrayArg, someType(type, t => isReadonlyArraySymbol(t.symbol.parent)));
|
||||
return (type as UnionType).arrayFallbackSignatures = getSignaturesOfType(getTypeOfPropertyOfType(arrayType, memberName!)!, kind);
|
||||
}
|
||||
(type as UnionType).arrayFallbackSignatures = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function isArrayOrTupleSymbol(symbol: Symbol | undefined) {
|
||||
if (!symbol || !globalArrayType.symbol || !globalReadonlyArrayType.symbol) {
|
||||
return false;
|
||||
}
|
||||
return !!getSymbolIfSameReference(symbol, globalArrayType.symbol) || !!getSymbolIfSameReference(symbol, globalReadonlyArrayType.symbol);
|
||||
}
|
||||
|
||||
function isReadonlyArraySymbol(symbol: Symbol | undefined) {
|
||||
if (!symbol || !globalReadonlyArrayType.symbol) {
|
||||
return false;
|
||||
}
|
||||
return !!getSymbolIfSameReference(symbol, globalReadonlyArrayType.symbol);
|
||||
}
|
||||
|
||||
function findIndexInfo(indexInfos: readonly IndexInfo[], keyType: Type) {
|
||||
|
||||
@ -6465,6 +6465,8 @@ export interface UnionType extends UnionOrIntersectionType {
|
||||
keyPropertyName?: __String; // Property with unique unit type that exists in every object/intersection in union type
|
||||
/** @internal */
|
||||
constituentMap?: Map<TypeId, Type>; // Constituents keyed by unit type discriminants
|
||||
/** @internal */
|
||||
arrayFallbackSignatures?: readonly Signature[]; // Special remapped signature list for unions of arrays
|
||||
}
|
||||
|
||||
export interface IntersectionType extends UnionOrIntersectionType {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
36
tests/baselines/reference/unionOfArraysFilterCall.js
Normal file
36
tests/baselines/reference/unionOfArraysFilterCall.js
Normal file
@ -0,0 +1,36 @@
|
||||
//// [unionOfArraysFilterCall.ts]
|
||||
interface Fizz {
|
||||
id: number;
|
||||
fizz: string;
|
||||
}
|
||||
|
||||
interface Buzz {
|
||||
id: number;
|
||||
buzz: string;
|
||||
}
|
||||
|
||||
([] as Fizz[] | Buzz[]).filter(item => item.id < 5);
|
||||
([] as Fizz[] | readonly Buzz[]).filter(item => item.id < 5);
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(item => item);
|
||||
declare function isFizz(x: unknown): x is Fizz;
|
||||
([] as Fizz[] | Buzz[]).find(isFizz);
|
||||
declare function isBuzz(x: unknown): x is Buzz;
|
||||
([] as Fizz[] | Buzz[]).find(isBuzz);
|
||||
|
||||
([] as Fizz[] | Buzz[]).every(item => item.id < 5);
|
||||
|
||||
([] as Fizz[] | Buzz[]).reduce(item => item);
|
||||
|
||||
|
||||
([] as [Fizz] | readonly [Buzz?]).filter(item => item?.id < 5);
|
||||
|
||||
//// [unionOfArraysFilterCall.js]
|
||||
[].filter(item => item.id < 5);
|
||||
[].filter(item => item.id < 5);
|
||||
[].find(item => item);
|
||||
[].find(isFizz);
|
||||
[].find(isBuzz);
|
||||
[].every(item => item.id < 5);
|
||||
[].reduce(item => item);
|
||||
[].filter(item => (item === null || item === void 0 ? void 0 : item.id) < 5);
|
||||
104
tests/baselines/reference/unionOfArraysFilterCall.symbols
Normal file
104
tests/baselines/reference/unionOfArraysFilterCall.symbols
Normal file
@ -0,0 +1,104 @@
|
||||
=== tests/cases/compiler/unionOfArraysFilterCall.ts ===
|
||||
interface Fizz {
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
|
||||
id: number;
|
||||
>id : Symbol(Fizz.id, Decl(unionOfArraysFilterCall.ts, 0, 16))
|
||||
|
||||
fizz: string;
|
||||
>fizz : Symbol(Fizz.fizz, Decl(unionOfArraysFilterCall.ts, 1, 15))
|
||||
}
|
||||
|
||||
interface Buzz {
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
|
||||
id: number;
|
||||
>id : Symbol(Buzz.id, Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
|
||||
buzz: string;
|
||||
>buzz : Symbol(Buzz.buzz, Decl(unionOfArraysFilterCall.ts, 6, 15))
|
||||
}
|
||||
|
||||
([] as Fizz[] | Buzz[]).filter(item => item.id < 5);
|
||||
>([] as Fizz[] | Buzz[]).filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 10, 31))
|
||||
>item.id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 10, 31))
|
||||
>id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
|
||||
([] as Fizz[] | readonly Buzz[]).filter(item => item.id < 5);
|
||||
>([] as Fizz[] | readonly Buzz[]).filter : Symbol(filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>filter : Symbol(filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 11, 40))
|
||||
>item.id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 11, 40))
|
||||
>id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(item => item);
|
||||
>([] as Fizz[] | Buzz[]).find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 13, 29))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 13, 29))
|
||||
|
||||
declare function isFizz(x: unknown): x is Fizz;
|
||||
>isFizz : Symbol(isFizz, Decl(unionOfArraysFilterCall.ts, 13, 43))
|
||||
>x : Symbol(x, Decl(unionOfArraysFilterCall.ts, 14, 24))
|
||||
>x : Symbol(x, Decl(unionOfArraysFilterCall.ts, 14, 24))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(isFizz);
|
||||
>([] as Fizz[] | Buzz[]).find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
|
||||
>isFizz : Symbol(isFizz, Decl(unionOfArraysFilterCall.ts, 13, 43))
|
||||
|
||||
declare function isBuzz(x: unknown): x is Buzz;
|
||||
>isBuzz : Symbol(isBuzz, Decl(unionOfArraysFilterCall.ts, 15, 37))
|
||||
>x : Symbol(x, Decl(unionOfArraysFilterCall.ts, 16, 24))
|
||||
>x : Symbol(x, Decl(unionOfArraysFilterCall.ts, 16, 24))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(isBuzz);
|
||||
>([] as Fizz[] | Buzz[]).find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
|
||||
>isBuzz : Symbol(isBuzz, Decl(unionOfArraysFilterCall.ts, 15, 37))
|
||||
|
||||
([] as Fizz[] | Buzz[]).every(item => item.id < 5);
|
||||
>([] as Fizz[] | Buzz[]).every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>every : Symbol(Array.every, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 19, 30))
|
||||
>item.id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 19, 30))
|
||||
>id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
|
||||
([] as Fizz[] | Buzz[]).reduce(item => item);
|
||||
>([] as Fizz[] | Buzz[]).reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 1 more)
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>reduce : Symbol(Array.reduce, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 1 more)
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 21, 31))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 21, 31))
|
||||
|
||||
|
||||
([] as [Fizz] | readonly [Buzz?]).filter(item => item?.id < 5);
|
||||
>([] as [Fizz] | readonly [Buzz?]).filter : Symbol(filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>Fizz : Symbol(Fizz, Decl(unionOfArraysFilterCall.ts, 0, 0))
|
||||
>Buzz : Symbol(Buzz, Decl(unionOfArraysFilterCall.ts, 3, 1))
|
||||
>filter : Symbol(filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 24, 41))
|
||||
>item?.id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
>item : Symbol(item, Decl(unionOfArraysFilterCall.ts, 24, 41))
|
||||
>id : Symbol(id, Decl(unionOfArraysFilterCall.ts, 0, 16), Decl(unionOfArraysFilterCall.ts, 5, 16))
|
||||
|
||||
126
tests/baselines/reference/unionOfArraysFilterCall.types
Normal file
126
tests/baselines/reference/unionOfArraysFilterCall.types
Normal file
@ -0,0 +1,126 @@
|
||||
=== tests/cases/compiler/unionOfArraysFilterCall.ts ===
|
||||
interface Fizz {
|
||||
id: number;
|
||||
>id : number
|
||||
|
||||
fizz: string;
|
||||
>fizz : string
|
||||
}
|
||||
|
||||
interface Buzz {
|
||||
id: number;
|
||||
>id : number
|
||||
|
||||
buzz: string;
|
||||
>buzz : string
|
||||
}
|
||||
|
||||
([] as Fizz[] | Buzz[]).filter(item => item.id < 5);
|
||||
>([] as Fizz[] | Buzz[]).filter(item => item.id < 5) : (Fizz | Buzz)[]
|
||||
>([] as Fizz[] | Buzz[]).filter : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): Fizz[]; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: Buzz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Buzz, index: number, array: Buzz[]) => unknown, thisArg?: any): Buzz[]; }
|
||||
>([] as Fizz[] | Buzz[]) : Fizz[] | Buzz[]
|
||||
>[] as Fizz[] | Buzz[] : Fizz[] | Buzz[]
|
||||
>[] : undefined[]
|
||||
>filter : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): Fizz[]; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: Buzz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Buzz, index: number, array: Buzz[]) => unknown, thisArg?: any): Buzz[]; }
|
||||
>item => item.id < 5 : (item: Fizz | Buzz) => boolean
|
||||
>item : Fizz | Buzz
|
||||
>item.id < 5 : boolean
|
||||
>item.id : number
|
||||
>item : Fizz | Buzz
|
||||
>id : number
|
||||
>5 : 5
|
||||
|
||||
([] as Fizz[] | readonly Buzz[]).filter(item => item.id < 5);
|
||||
>([] as Fizz[] | readonly Buzz[]).filter(item => item.id < 5) : (Fizz | Buzz)[]
|
||||
>([] as Fizz[] | readonly Buzz[]).filter : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): Fizz[]; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: readonly Buzz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Buzz, index: number, array: readonly Buzz[]) => unknown, thisArg?: any): Buzz[]; }
|
||||
>([] as Fizz[] | readonly Buzz[]) : Fizz[] | readonly Buzz[]
|
||||
>[] as Fizz[] | readonly Buzz[] : Fizz[] | readonly Buzz[]
|
||||
>[] : undefined[]
|
||||
>filter : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): Fizz[]; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: readonly Buzz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Buzz, index: number, array: readonly Buzz[]) => unknown, thisArg?: any): Buzz[]; }
|
||||
>item => item.id < 5 : (item: Fizz | Buzz) => boolean
|
||||
>item : Fizz | Buzz
|
||||
>item.id < 5 : boolean
|
||||
>item.id : number
|
||||
>item : Fizz | Buzz
|
||||
>id : number
|
||||
>5 : 5
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(item => item);
|
||||
>([] as Fizz[] | Buzz[]).find(item => item) : Fizz | Buzz
|
||||
>([] as Fizz[] | Buzz[]).find : { <S extends Fizz>(predicate: (value: Fizz, index: number, obj: Fizz[]) => value is S, thisArg?: any): S; (predicate: (value: Fizz, index: number, obj: Fizz[]) => unknown, thisArg?: any): Fizz; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, obj: Buzz[]) => value is S, thisArg?: any): S; (predicate: (value: Buzz, index: number, obj: Buzz[]) => unknown, thisArg?: any): Buzz; }
|
||||
>([] as Fizz[] | Buzz[]) : Fizz[] | Buzz[]
|
||||
>[] as Fizz[] | Buzz[] : Fizz[] | Buzz[]
|
||||
>[] : undefined[]
|
||||
>find : { <S extends Fizz>(predicate: (value: Fizz, index: number, obj: Fizz[]) => value is S, thisArg?: any): S; (predicate: (value: Fizz, index: number, obj: Fizz[]) => unknown, thisArg?: any): Fizz; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, obj: Buzz[]) => value is S, thisArg?: any): S; (predicate: (value: Buzz, index: number, obj: Buzz[]) => unknown, thisArg?: any): Buzz; }
|
||||
>item => item : (item: Fizz | Buzz) => Fizz | Buzz
|
||||
>item : Fizz | Buzz
|
||||
>item : Fizz | Buzz
|
||||
|
||||
declare function isFizz(x: unknown): x is Fizz;
|
||||
>isFizz : (x: unknown) => x is Fizz
|
||||
>x : unknown
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(isFizz);
|
||||
>([] as Fizz[] | Buzz[]).find(isFizz) : Fizz
|
||||
>([] as Fizz[] | Buzz[]).find : { <S extends Fizz>(predicate: (value: Fizz, index: number, obj: Fizz[]) => value is S, thisArg?: any): S; (predicate: (value: Fizz, index: number, obj: Fizz[]) => unknown, thisArg?: any): Fizz; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, obj: Buzz[]) => value is S, thisArg?: any): S; (predicate: (value: Buzz, index: number, obj: Buzz[]) => unknown, thisArg?: any): Buzz; }
|
||||
>([] as Fizz[] | Buzz[]) : Fizz[] | Buzz[]
|
||||
>[] as Fizz[] | Buzz[] : Fizz[] | Buzz[]
|
||||
>[] : undefined[]
|
||||
>find : { <S extends Fizz>(predicate: (value: Fizz, index: number, obj: Fizz[]) => value is S, thisArg?: any): S; (predicate: (value: Fizz, index: number, obj: Fizz[]) => unknown, thisArg?: any): Fizz; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, obj: Buzz[]) => value is S, thisArg?: any): S; (predicate: (value: Buzz, index: number, obj: Buzz[]) => unknown, thisArg?: any): Buzz; }
|
||||
>isFizz : (x: unknown) => x is Fizz
|
||||
|
||||
declare function isBuzz(x: unknown): x is Buzz;
|
||||
>isBuzz : (x: unknown) => x is Buzz
|
||||
>x : unknown
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(isBuzz);
|
||||
>([] as Fizz[] | Buzz[]).find(isBuzz) : Buzz
|
||||
>([] as Fizz[] | Buzz[]).find : { <S extends Fizz>(predicate: (value: Fizz, index: number, obj: Fizz[]) => value is S, thisArg?: any): S; (predicate: (value: Fizz, index: number, obj: Fizz[]) => unknown, thisArg?: any): Fizz; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, obj: Buzz[]) => value is S, thisArg?: any): S; (predicate: (value: Buzz, index: number, obj: Buzz[]) => unknown, thisArg?: any): Buzz; }
|
||||
>([] as Fizz[] | Buzz[]) : Fizz[] | Buzz[]
|
||||
>[] as Fizz[] | Buzz[] : Fizz[] | Buzz[]
|
||||
>[] : undefined[]
|
||||
>find : { <S extends Fizz>(predicate: (value: Fizz, index: number, obj: Fizz[]) => value is S, thisArg?: any): S; (predicate: (value: Fizz, index: number, obj: Fizz[]) => unknown, thisArg?: any): Fizz; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, obj: Buzz[]) => value is S, thisArg?: any): S; (predicate: (value: Buzz, index: number, obj: Buzz[]) => unknown, thisArg?: any): Buzz; }
|
||||
>isBuzz : (x: unknown) => x is Buzz
|
||||
|
||||
([] as Fizz[] | Buzz[]).every(item => item.id < 5);
|
||||
>([] as Fizz[] | Buzz[]).every(item => item.id < 5) : boolean
|
||||
>([] as Fizz[] | Buzz[]).every : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): boolean; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: Buzz[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Buzz, index: number, array: Buzz[]) => unknown, thisArg?: any): boolean; }
|
||||
>([] as Fizz[] | Buzz[]) : Fizz[] | Buzz[]
|
||||
>[] as Fizz[] | Buzz[] : Fizz[] | Buzz[]
|
||||
>[] : undefined[]
|
||||
>every : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): boolean; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: Buzz[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: Buzz, index: number, array: Buzz[]) => unknown, thisArg?: any): boolean; }
|
||||
>item => item.id < 5 : (item: Fizz | Buzz) => boolean
|
||||
>item : Fizz | Buzz
|
||||
>item.id < 5 : boolean
|
||||
>item.id : number
|
||||
>item : Fizz | Buzz
|
||||
>id : number
|
||||
>5 : 5
|
||||
|
||||
([] as Fizz[] | Buzz[]).reduce(item => item);
|
||||
>([] as Fizz[] | Buzz[]).reduce(item => item) : Fizz | Buzz
|
||||
>([] as Fizz[] | Buzz[]).reduce : { (callbackfn: (previousValue: Fizz, currentValue: Fizz, currentIndex: number, array: Fizz[]) => Fizz): Fizz; (callbackfn: (previousValue: Fizz, currentValue: Fizz, currentIndex: number, array: Fizz[]) => Fizz, initialValue: Fizz): Fizz; <U>(callbackfn: (previousValue: U, currentValue: Fizz, currentIndex: number, array: Fizz[]) => U, initialValue: U): U; } | { (callbackfn: (previousValue: Buzz, currentValue: Buzz, currentIndex: number, array: Buzz[]) => Buzz): Buzz; (callbackfn: (previousValue: Buzz, currentValue: Buzz, currentIndex: number, array: Buzz[]) => Buzz, initialValue: Buzz): Buzz; <U>(callbackfn: (previousValue: U, currentValue: Buzz, currentIndex: number, array: Buzz[]) => U, initialValue: U): U; }
|
||||
>([] as Fizz[] | Buzz[]) : Fizz[] | Buzz[]
|
||||
>[] as Fizz[] | Buzz[] : Fizz[] | Buzz[]
|
||||
>[] : undefined[]
|
||||
>reduce : { (callbackfn: (previousValue: Fizz, currentValue: Fizz, currentIndex: number, array: Fizz[]) => Fizz): Fizz; (callbackfn: (previousValue: Fizz, currentValue: Fizz, currentIndex: number, array: Fizz[]) => Fizz, initialValue: Fizz): Fizz; <U>(callbackfn: (previousValue: U, currentValue: Fizz, currentIndex: number, array: Fizz[]) => U, initialValue: U): U; } | { (callbackfn: (previousValue: Buzz, currentValue: Buzz, currentIndex: number, array: Buzz[]) => Buzz): Buzz; (callbackfn: (previousValue: Buzz, currentValue: Buzz, currentIndex: number, array: Buzz[]) => Buzz, initialValue: Buzz): Buzz; <U>(callbackfn: (previousValue: U, currentValue: Buzz, currentIndex: number, array: Buzz[]) => U, initialValue: U): U; }
|
||||
>item => item : (item: Fizz | Buzz) => Fizz | Buzz
|
||||
>item : Fizz | Buzz
|
||||
>item : Fizz | Buzz
|
||||
|
||||
|
||||
([] as [Fizz] | readonly [Buzz?]).filter(item => item?.id < 5);
|
||||
>([] as [Fizz] | readonly [Buzz?]).filter(item => item?.id < 5) : (Fizz | Buzz)[]
|
||||
>([] as [Fizz] | readonly [Buzz?]).filter : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): Fizz[]; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: readonly Buzz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Buzz, index: number, array: readonly Buzz[]) => unknown, thisArg?: any): Buzz[]; }
|
||||
>([] as [Fizz] | readonly [Buzz?]) : [Fizz] | readonly [Buzz?]
|
||||
>[] as [Fizz] | readonly [Buzz?] : [Fizz] | readonly [Buzz?]
|
||||
>[] : []
|
||||
>filter : { <S extends Fizz>(predicate: (value: Fizz, index: number, array: Fizz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Fizz, index: number, array: Fizz[]) => unknown, thisArg?: any): Fizz[]; } | { <S extends Buzz>(predicate: (value: Buzz, index: number, array: readonly Buzz[]) => value is S, thisArg?: any): S[]; (predicate: (value: Buzz, index: number, array: readonly Buzz[]) => unknown, thisArg?: any): Buzz[]; }
|
||||
>item => item?.id < 5 : (item: Fizz | Buzz) => boolean
|
||||
>item : Fizz | Buzz
|
||||
>item?.id < 5 : boolean
|
||||
>item?.id : number
|
||||
>item : Fizz | Buzz
|
||||
>id : number
|
||||
>5 : 5
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
tests/cases/compiler/unionOfClassCalls.ts(28,5): error TS2349: This expression is not callable.
|
||||
Each member of the union type '{ (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } | { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }' has signatures, but none of those signatures are compatible with each other.
|
||||
|
||||
|
||||
==== tests/cases/compiler/unionOfClassCalls.ts (1 errors) ====
|
||||
// from https://github.com/microsoft/TypeScript/issues/30717
|
||||
declare class Test<T> {
|
||||
obj: T;
|
||||
get<K extends keyof T>(k: K): T[K];
|
||||
}
|
||||
|
||||
interface A { t: "A" }
|
||||
interface B { t: "B" }
|
||||
|
||||
declare const tmp: Test<A> | Test<B>;
|
||||
|
||||
switch (tmp.get('t')) {
|
||||
case 'A': break;
|
||||
case 'B': break;
|
||||
}
|
||||
|
||||
// from https://github.com/microsoft/TypeScript/issues/36390
|
||||
|
||||
const arr: number[] | string[] = []; // Works with Array<number | string>
|
||||
const arr1: number[] = [];
|
||||
const arr2: string[] = [];
|
||||
|
||||
arr.map((a: number | string, index: number) => {
|
||||
return index
|
||||
})
|
||||
|
||||
// This case still doesn't work because `reduce` has multiple overloads :(
|
||||
arr.reduce((acc: Array<string>, a: number | string, index: number) => {
|
||||
~~~~~~
|
||||
!!! error TS2349: This expression is not callable.
|
||||
!!! error TS2349: Each member of the union type '{ (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } | { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }' has signatures, but none of those signatures are compatible with each other.
|
||||
return []
|
||||
}, [])
|
||||
|
||||
arr.forEach((a: number | string, index: number) => {
|
||||
return index
|
||||
})
|
||||
|
||||
arr1.map((a: number, index: number) => {
|
||||
return index
|
||||
})
|
||||
|
||||
arr1.reduce((acc: number[], a: number, index: number) => {
|
||||
return [a]
|
||||
}, [])
|
||||
|
||||
arr1.forEach((a: number, index: number) => {
|
||||
return index
|
||||
})
|
||||
arr2.map((a: string, index: number) => {
|
||||
return index
|
||||
})
|
||||
|
||||
arr2.reduce((acc: string[], a: string, index: number) => {
|
||||
return []
|
||||
}, [])
|
||||
|
||||
arr2.forEach((a: string, index: number) => {
|
||||
return index
|
||||
})
|
||||
|
||||
// from https://github.com/microsoft/TypeScript/issues/36307
|
||||
|
||||
declare class Foo {
|
||||
doThing(): Promise<this>
|
||||
}
|
||||
|
||||
declare class Bar extends Foo {
|
||||
bar: number;
|
||||
}
|
||||
declare class Baz extends Foo {
|
||||
baz: number;
|
||||
}
|
||||
|
||||
declare var a: Bar | Baz;
|
||||
// note, you must annotate `result` for now
|
||||
a.doThing().then((result: Bar | Baz) => {
|
||||
// whatever
|
||||
});
|
||||
|
||||
@ -64,7 +64,7 @@ arr.map((a: number | string, index: number) => {
|
||||
|
||||
// This case still doesn't work because `reduce` has multiple overloads :(
|
||||
arr.reduce((acc: Array<string>, a: number | string, index: number) => {
|
||||
>arr.reduce((acc: Array<string>, a: number | string, index: number) => { return []}, []) : any
|
||||
>arr.reduce((acc: Array<string>, a: number | string, index: number) => { return []}, []) : never[]
|
||||
>arr.reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } | { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }
|
||||
>arr : number[] | string[]
|
||||
>reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } | { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }
|
||||
|
||||
26
tests/cases/compiler/unionOfArraysFilterCall.ts
Normal file
26
tests/cases/compiler/unionOfArraysFilterCall.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// @target: es6
|
||||
interface Fizz {
|
||||
id: number;
|
||||
fizz: string;
|
||||
}
|
||||
|
||||
interface Buzz {
|
||||
id: number;
|
||||
buzz: string;
|
||||
}
|
||||
|
||||
([] as Fizz[] | Buzz[]).filter(item => item.id < 5);
|
||||
([] as Fizz[] | readonly Buzz[]).filter(item => item.id < 5);
|
||||
|
||||
([] as Fizz[] | Buzz[]).find(item => item);
|
||||
declare function isFizz(x: unknown): x is Fizz;
|
||||
([] as Fizz[] | Buzz[]).find(isFizz);
|
||||
declare function isBuzz(x: unknown): x is Buzz;
|
||||
([] as Fizz[] | Buzz[]).find(isBuzz);
|
||||
|
||||
([] as Fizz[] | Buzz[]).every(item => item.id < 5);
|
||||
|
||||
([] as Fizz[] | Buzz[]).reduce(item => item);
|
||||
|
||||
|
||||
([] as [Fizz] | readonly [Buzz?]).filter(item => item?.id < 5);
|
||||
Loading…
x
Reference in New Issue
Block a user