Filter return type inferences by constraint applicability (#58910)

This commit is contained in:
Mateusz Burzyński 2025-12-03 18:46:59 +01:00 committed by GitHub
parent 5026c6675c
commit 28fbc0a1ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 890 additions and 3 deletions

View File

@ -27576,10 +27576,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const constraint = getConstraintOfTypeParameter(inference.typeParameter);
if (constraint) {
const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
// If the fallback type satisfies the constraint, we pick it. Otherwise, we pick the constraint.
inference.inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint;
if (inferredType) {
const constraintWithThis = getTypeWithThisArgument(instantiatedConstraint, inferredType);
if (!context.compareTypes(inferredType, constraintWithThis)) {
// If we have a pure return type inference, we may succeed by removing constituents of the inferred type
// that aren't assignable to the constraint type (pure return type inferences are speculation anyway).
const filteredByConstraint = inference.priority === InferencePriority.ReturnType ? filterType(inferredType, t => !!context.compareTypes(t, constraintWithThis)) : neverType;
inferredType = !(filteredByConstraint.flags & TypeFlags.Never) ? filteredByConstraint : undefined;
}
}
if (!inferredType) {
// If the fallback type satisfies the constraint, we pick it. Otherwise, we pick the constraint.
inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint;
}
inference.inferredType = inferredType;
}
clearActiveMapperCaches();
}

View File

@ -0,0 +1,53 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion1.ts] ////
=== inferenceContextualReturnTypeUnion1.ts ===
// https://github.com/microsoft/TypeScript/issues/50719
declare function useCallback1<T extends Function>(fn: T): T;
>useCallback1 : Symbol(useCallback1, Decl(inferenceContextualReturnTypeUnion1.ts, 0, 0))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion1.ts, 2, 30))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>fn : Symbol(fn, Decl(inferenceContextualReturnTypeUnion1.ts, 2, 50))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion1.ts, 2, 30))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion1.ts, 2, 30))
declare function ex2(callback?: (x: number) => void): void;
>ex2 : Symbol(ex2, Decl(inferenceContextualReturnTypeUnion1.ts, 2, 60))
>callback : Symbol(callback, Decl(inferenceContextualReturnTypeUnion1.ts, 4, 21))
>x : Symbol(x, Decl(inferenceContextualReturnTypeUnion1.ts, 4, 33))
ex2(useCallback1((x) => {}));
>ex2 : Symbol(ex2, Decl(inferenceContextualReturnTypeUnion1.ts, 2, 60))
>useCallback1 : Symbol(useCallback1, Decl(inferenceContextualReturnTypeUnion1.ts, 0, 0))
>x : Symbol(x, Decl(inferenceContextualReturnTypeUnion1.ts, 5, 18))
declare function ex3(callback: ((x: number) => void) | 5): void;
>ex3 : Symbol(ex3, Decl(inferenceContextualReturnTypeUnion1.ts, 5, 29))
>callback : Symbol(callback, Decl(inferenceContextualReturnTypeUnion1.ts, 7, 21))
>x : Symbol(x, Decl(inferenceContextualReturnTypeUnion1.ts, 7, 33))
ex3(useCallback1((x) => {}));
>ex3 : Symbol(ex3, Decl(inferenceContextualReturnTypeUnion1.ts, 5, 29))
>useCallback1 : Symbol(useCallback1, Decl(inferenceContextualReturnTypeUnion1.ts, 0, 0))
>x : Symbol(x, Decl(inferenceContextualReturnTypeUnion1.ts, 8, 18))
// https://github.com/microsoft/TypeScript/issues/41461
declare function useCallback2<T extends (...args: any[]) => any>(
>useCallback2 : Symbol(useCallback2, Decl(inferenceContextualReturnTypeUnion1.ts, 8, 29))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion1.ts, 12, 30))
>args : Symbol(args, Decl(inferenceContextualReturnTypeUnion1.ts, 12, 41))
callback: T,
>callback : Symbol(callback, Decl(inferenceContextualReturnTypeUnion1.ts, 12, 65))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion1.ts, 12, 30))
): T;
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion1.ts, 12, 30))
const test: ((x: string) => void) | undefined = useCallback2((x) => {});
>test : Symbol(test, Decl(inferenceContextualReturnTypeUnion1.ts, 15, 5))
>x : Symbol(x, Decl(inferenceContextualReturnTypeUnion1.ts, 15, 14))
>useCallback2 : Symbol(useCallback2, Decl(inferenceContextualReturnTypeUnion1.ts, 8, 29))
>x : Symbol(x, Decl(inferenceContextualReturnTypeUnion1.ts, 15, 62))

View File

@ -0,0 +1,82 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion1.ts] ////
=== inferenceContextualReturnTypeUnion1.ts ===
// https://github.com/microsoft/TypeScript/issues/50719
declare function useCallback1<T extends Function>(fn: T): T;
>useCallback1 : <T extends Function>(fn: T) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>fn : T
> : ^
declare function ex2(callback?: (x: number) => void): void;
>ex2 : (callback?: (x: number) => void) => void
> : ^ ^^^ ^^^^^
>callback : ((x: number) => void) | undefined
> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^
>x : number
> : ^^^^^^
ex2(useCallback1((x) => {}));
>ex2(useCallback1((x) => {})) : void
> : ^^^^
>ex2 : (callback?: (x: number) => void) => void
> : ^ ^^^ ^^^^^
>useCallback1((x) => {}) : (x: number) => void
> : ^ ^^^^^^^^^^^^^^^^^
>useCallback1 : <T extends Function>(fn: T) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>(x) => {} : (x: number) => void
> : ^ ^^^^^^^^^^^^^^^^^
>x : number
> : ^^^^^^
declare function ex3(callback: ((x: number) => void) | 5): void;
>ex3 : (callback: ((x: number) => void) | 5) => void
> : ^ ^^ ^^^^^
>callback : ((x: number) => void) | 5
> : ^^ ^^ ^^^^^ ^^^^^
>x : number
> : ^^^^^^
ex3(useCallback1((x) => {}));
>ex3(useCallback1((x) => {})) : void
> : ^^^^
>ex3 : (callback: ((x: number) => void) | 5) => void
> : ^ ^^ ^^^^^
>useCallback1((x) => {}) : (x: number) => void
> : ^ ^^^^^^^^^^^^^^^^^
>useCallback1 : <T extends Function>(fn: T) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>(x) => {} : (x: number) => void
> : ^ ^^^^^^^^^^^^^^^^^
>x : number
> : ^^^^^^
// https://github.com/microsoft/TypeScript/issues/41461
declare function useCallback2<T extends (...args: any[]) => any>(
>useCallback2 : <T extends (...args: any[]) => any>(callback: T) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>args : any[]
> : ^^^^^
callback: T,
>callback : T
> : ^
): T;
const test: ((x: string) => void) | undefined = useCallback2((x) => {});
>test : ((x: string) => void) | undefined
> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^
>x : string
> : ^^^^^^
>useCallback2((x) => {}) : (x: string) => void
> : ^ ^^^^^^^^^^^^^^^^^
>useCallback2 : <T extends (...args: any[]) => any>(callback: T) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>(x) => {} : (x: string) => void
> : ^ ^^^^^^^^^^^^^^^^^
>x : string
> : ^^^^^^

View File

@ -0,0 +1,97 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion2.ts] ////
=== inferenceContextualReturnTypeUnion2.ts ===
type Query = (
>Query : Symbol(Query, Decl(inferenceContextualReturnTypeUnion2.ts, 0, 0))
container: HTMLElement,
>container : Symbol(container, Decl(inferenceContextualReturnTypeUnion2.ts, 0, 14))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
...args: any[]
>args : Symbol(args, Decl(inferenceContextualReturnTypeUnion2.ts, 1, 25))
) =>
| Error
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --))
| HTMLElement
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
| HTMLElement[]
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
| Promise<HTMLElement[]>
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
| Promise<HTMLElement>
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
| null;
interface Queries {
>Queries : Symbol(Queries, Decl(inferenceContextualReturnTypeUnion2.ts, 9, 9))
[T: string]: Query;
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion2.ts, 12, 3))
>Query : Symbol(Query, Decl(inferenceContextualReturnTypeUnion2.ts, 0, 0))
}
type FindByText<T extends HTMLElement = HTMLElement> = (
>FindByText : Symbol(FindByText, Decl(inferenceContextualReturnTypeUnion2.ts, 13, 1))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion2.ts, 15, 16))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
container: HTMLElement,
>container : Symbol(container, Decl(inferenceContextualReturnTypeUnion2.ts, 15, 56))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
text: string,
>text : Symbol(text, Decl(inferenceContextualReturnTypeUnion2.ts, 16, 25))
) => Promise<T>;
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion2.ts, 15, 16))
declare function findByLabelText<T extends HTMLElement = HTMLElement>(
>findByLabelText : Symbol(findByLabelText, Decl(inferenceContextualReturnTypeUnion2.ts, 18, 16))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion2.ts, 20, 33))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
...args: Parameters<FindByText<T>>
>args : Symbol(args, Decl(inferenceContextualReturnTypeUnion2.ts, 20, 70))
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
>FindByText : Symbol(FindByText, Decl(inferenceContextualReturnTypeUnion2.ts, 13, 1))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion2.ts, 20, 33))
): ReturnType<FindByText<T>>;
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
>FindByText : Symbol(FindByText, Decl(inferenceContextualReturnTypeUnion2.ts, 13, 1))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion2.ts, 20, 33))
const queries = {
>queries : Symbol(queries, Decl(inferenceContextualReturnTypeUnion2.ts, 24, 5))
findByLabelText,
>findByLabelText : Symbol(findByLabelText, Decl(inferenceContextualReturnTypeUnion2.ts, 24, 17))
};
type MapQueries<Q extends Queries = typeof queries> = {
>MapQueries : Symbol(MapQueries, Decl(inferenceContextualReturnTypeUnion2.ts, 26, 2))
>Q : Symbol(Q, Decl(inferenceContextualReturnTypeUnion2.ts, 28, 16))
>Queries : Symbol(Queries, Decl(inferenceContextualReturnTypeUnion2.ts, 9, 9))
>queries : Symbol(queries, Decl(inferenceContextualReturnTypeUnion2.ts, 24, 5))
[P in keyof Q]: Q[P];
>P : Symbol(P, Decl(inferenceContextualReturnTypeUnion2.ts, 29, 3))
>Q : Symbol(Q, Decl(inferenceContextualReturnTypeUnion2.ts, 28, 16))
>Q : Symbol(Q, Decl(inferenceContextualReturnTypeUnion2.ts, 28, 16))
>P : Symbol(P, Decl(inferenceContextualReturnTypeUnion2.ts, 29, 3))
};

View File

@ -0,0 +1,74 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion2.ts] ////
=== inferenceContextualReturnTypeUnion2.ts ===
type Query = (
>Query : Query
> : ^^^^^
container: HTMLElement,
>container : HTMLElement
> : ^^^^^^^^^^^
...args: any[]
>args : any[]
> : ^^^^^
) =>
| Error
| HTMLElement
| HTMLElement[]
| Promise<HTMLElement[]>
| Promise<HTMLElement>
| null;
interface Queries {
[T: string]: Query;
>T : string
> : ^^^^^^
}
type FindByText<T extends HTMLElement = HTMLElement> = (
>FindByText : FindByText<T>
> : ^^^^^^^^^^^^^
container: HTMLElement,
>container : HTMLElement
> : ^^^^^^^^^^^
text: string,
>text : string
> : ^^^^^^
) => Promise<T>;
declare function findByLabelText<T extends HTMLElement = HTMLElement>(
>findByLabelText : <T extends HTMLElement = HTMLElement>(container: HTMLElement, text: string) => ReturnType<FindByText<T>>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...args: Parameters<FindByText<T>>
>args : [container: HTMLElement, text: string]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
): ReturnType<FindByText<T>>;
const queries = {
>queries : { findByLabelText: <T extends HTMLElement = HTMLElement>(container: HTMLElement, text: string) => ReturnType<FindByText<T>>; }
> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
>{ findByLabelText,} : { findByLabelText: <T extends HTMLElement = HTMLElement>(container: HTMLElement, text: string) => ReturnType<FindByText<T>>; }
> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
findByLabelText,
>findByLabelText : <T extends HTMLElement = HTMLElement>(container: HTMLElement, text: string) => ReturnType<FindByText<T>>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
};
type MapQueries<Q extends Queries = typeof queries> = {
>MapQueries : MapQueries<Q>
> : ^^^^^^^^^^^^^
>queries : { findByLabelText: <T extends HTMLElement = HTMLElement>(container: HTMLElement, text: string) => ReturnType<FindByText<T>>; }
> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
[P in keyof Q]: Q[P];
};

View File

@ -0,0 +1,146 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion3.ts] ////
=== inferenceContextualReturnTypeUnion3.ts ===
declare function deprecate<T extends Function>(
>deprecate : Symbol(deprecate, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 0))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 27))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.decorators.d.ts, --, --))
fn: T,
>fn : Symbol(fn, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 47))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 27))
msg: string,
>msg : Symbol(msg, Decl(inferenceContextualReturnTypeUnion3.ts, 1, 8))
code?: string,
>code : Symbol(code, Decl(inferenceContextualReturnTypeUnion3.ts, 2, 14))
): T;
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 27))
const soonFrozenObjectDeprecation = <T extends object>(
>soonFrozenObjectDeprecation : Symbol(soonFrozenObjectDeprecation, Decl(inferenceContextualReturnTypeUnion3.ts, 6, 5))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion3.ts, 6, 37))
obj: T,
>obj : Symbol(obj, Decl(inferenceContextualReturnTypeUnion3.ts, 6, 55))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion3.ts, 6, 37))
name: string,
>name : Symbol(name, Decl(inferenceContextualReturnTypeUnion3.ts, 7, 9))
code: string,
>code : Symbol(code, Decl(inferenceContextualReturnTypeUnion3.ts, 8, 15))
note = "",
>note : Symbol(note, Decl(inferenceContextualReturnTypeUnion3.ts, 9, 15))
): T => {
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion3.ts, 6, 37))
const message = `${name} will be frozen in future, all modifications are deprecated.${
>message : Symbol(message, Decl(inferenceContextualReturnTypeUnion3.ts, 12, 7))
>name : Symbol(name, Decl(inferenceContextualReturnTypeUnion3.ts, 7, 9))
note && `\n${note}`
>note : Symbol(note, Decl(inferenceContextualReturnTypeUnion3.ts, 9, 15))
>note : Symbol(note, Decl(inferenceContextualReturnTypeUnion3.ts, 9, 15))
}`;
return new Proxy(obj, {
>Proxy : Symbol(Proxy, Decl(lib.es2015.proxy.d.ts, --, --))
>obj : Symbol(obj, Decl(inferenceContextualReturnTypeUnion3.ts, 6, 55))
set: deprecate(
>set : Symbol(set, Decl(inferenceContextualReturnTypeUnion3.ts, 15, 25))
>deprecate : Symbol(deprecate, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 0))
(target, property, value, receiver) =>
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 7))
>property : Symbol(property, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 14))
>value : Symbol(value, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 24))
>receiver : Symbol(receiver, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 31))
Reflect.set(target, property, value, receiver),
>Reflect.set : Symbol(Reflect.set, Decl(lib.es2015.reflect.d.ts, --, --), Decl(lib.es2015.reflect.d.ts, --, --))
>Reflect : Symbol(Reflect, Decl(lib.es2015.reflect.d.ts, --, --))
>set : Symbol(Reflect.set, Decl(lib.es2015.reflect.d.ts, --, --), Decl(lib.es2015.reflect.d.ts, --, --))
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 7))
>property : Symbol(property, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 14))
>value : Symbol(value, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 24))
>receiver : Symbol(receiver, Decl(inferenceContextualReturnTypeUnion3.ts, 17, 31))
message,
>message : Symbol(message, Decl(inferenceContextualReturnTypeUnion3.ts, 12, 7))
code,
>code : Symbol(code, Decl(inferenceContextualReturnTypeUnion3.ts, 8, 15))
),
defineProperty: deprecate(
>defineProperty : Symbol(defineProperty, Decl(inferenceContextualReturnTypeUnion3.ts, 21, 6))
>deprecate : Symbol(deprecate, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 0))
(target, property, descriptor) =>
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 23, 7))
>property : Symbol(property, Decl(inferenceContextualReturnTypeUnion3.ts, 23, 14))
>descriptor : Symbol(descriptor, Decl(inferenceContextualReturnTypeUnion3.ts, 23, 24))
Reflect.defineProperty(target, property, descriptor),
>Reflect.defineProperty : Symbol(Reflect.defineProperty, Decl(lib.es2015.reflect.d.ts, --, --))
>Reflect : Symbol(Reflect, Decl(lib.es2015.reflect.d.ts, --, --))
>defineProperty : Symbol(Reflect.defineProperty, Decl(lib.es2015.reflect.d.ts, --, --))
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 23, 7))
>property : Symbol(property, Decl(inferenceContextualReturnTypeUnion3.ts, 23, 14))
>descriptor : Symbol(descriptor, Decl(inferenceContextualReturnTypeUnion3.ts, 23, 24))
message,
>message : Symbol(message, Decl(inferenceContextualReturnTypeUnion3.ts, 12, 7))
code,
>code : Symbol(code, Decl(inferenceContextualReturnTypeUnion3.ts, 8, 15))
),
deleteProperty: deprecate(
>deleteProperty : Symbol(deleteProperty, Decl(inferenceContextualReturnTypeUnion3.ts, 27, 6))
>deprecate : Symbol(deprecate, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 0))
(target, property) => Reflect.deleteProperty(target, property),
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 29, 7))
>property : Symbol(property, Decl(inferenceContextualReturnTypeUnion3.ts, 29, 14))
>Reflect.deleteProperty : Symbol(Reflect.deleteProperty, Decl(lib.es2015.reflect.d.ts, --, --))
>Reflect : Symbol(Reflect, Decl(lib.es2015.reflect.d.ts, --, --))
>deleteProperty : Symbol(Reflect.deleteProperty, Decl(lib.es2015.reflect.d.ts, --, --))
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 29, 7))
>property : Symbol(property, Decl(inferenceContextualReturnTypeUnion3.ts, 29, 14))
message,
>message : Symbol(message, Decl(inferenceContextualReturnTypeUnion3.ts, 12, 7))
code,
>code : Symbol(code, Decl(inferenceContextualReturnTypeUnion3.ts, 8, 15))
),
setPrototypeOf: deprecate(
>setPrototypeOf : Symbol(setPrototypeOf, Decl(inferenceContextualReturnTypeUnion3.ts, 32, 6))
>deprecate : Symbol(deprecate, Decl(inferenceContextualReturnTypeUnion3.ts, 0, 0))
(target, proto) => Reflect.setPrototypeOf(target, proto),
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 34, 7))
>proto : Symbol(proto, Decl(inferenceContextualReturnTypeUnion3.ts, 34, 14))
>Reflect.setPrototypeOf : Symbol(Reflect.setPrototypeOf, Decl(lib.es2015.reflect.d.ts, --, --))
>Reflect : Symbol(Reflect, Decl(lib.es2015.reflect.d.ts, --, --))
>setPrototypeOf : Symbol(Reflect.setPrototypeOf, Decl(lib.es2015.reflect.d.ts, --, --))
>target : Symbol(target, Decl(inferenceContextualReturnTypeUnion3.ts, 34, 7))
>proto : Symbol(proto, Decl(inferenceContextualReturnTypeUnion3.ts, 34, 14))
message,
>message : Symbol(message, Decl(inferenceContextualReturnTypeUnion3.ts, 12, 7))
code,
>code : Symbol(code, Decl(inferenceContextualReturnTypeUnion3.ts, 8, 15))
),
});
};

View File

@ -0,0 +1,237 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion3.ts] ////
=== inferenceContextualReturnTypeUnion3.ts ===
declare function deprecate<T extends Function>(
>deprecate : <T extends Function>(fn: T, msg: string, code?: string) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^
fn: T,
>fn : T
> : ^
msg: string,
>msg : string
> : ^^^^^^
code?: string,
>code : string | undefined
> : ^^^^^^^^^^^^^^^^^^
): T;
const soonFrozenObjectDeprecation = <T extends object>(
>soonFrozenObjectDeprecation : <T extends object>(obj: T, name: string, code: string, note?: string) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^
><T extends object>( obj: T, name: string, code: string, note = "",): T => { const message = `${name} will be frozen in future, all modifications are deprecated.${ note && `\n${note}` }`; return new Proxy(obj, { set: deprecate( (target, property, value, receiver) => Reflect.set(target, property, value, receiver), message, code, ), defineProperty: deprecate( (target, property, descriptor) => Reflect.defineProperty(target, property, descriptor), message, code, ), deleteProperty: deprecate( (target, property) => Reflect.deleteProperty(target, property), message, code, ), setPrototypeOf: deprecate( (target, proto) => Reflect.setPrototypeOf(target, proto), message, code, ), });} : <T extends object>(obj: T, name: string, code: string, note?: string) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^
obj: T,
>obj : T
> : ^
name: string,
>name : string
> : ^^^^^^
code: string,
>code : string
> : ^^^^^^
note = "",
>note : string
> : ^^^^^^
>"" : ""
> : ^^
): T => {
const message = `${name} will be frozen in future, all modifications are deprecated.${
>message : string
> : ^^^^^^
>`${name} will be frozen in future, all modifications are deprecated.${ note && `\n${note}` }` : string
> : ^^^^^^
>name : string
> : ^^^^^^
note && `\n${note}`
>note && `\n${note}` : string
> : ^^^^^^
>note : string
> : ^^^^^^
>`\n${note}` : string
> : ^^^^^^
>note : string
> : ^^^^^^
}`;
return new Proxy(obj, {
>new Proxy(obj, { set: deprecate( (target, property, value, receiver) => Reflect.set(target, property, value, receiver), message, code, ), defineProperty: deprecate( (target, property, descriptor) => Reflect.defineProperty(target, property, descriptor), message, code, ), deleteProperty: deprecate( (target, property) => Reflect.deleteProperty(target, property), message, code, ), setPrototypeOf: deprecate( (target, proto) => Reflect.setPrototypeOf(target, proto), message, code, ), }) : T
> : ^
>Proxy : ProxyConstructor
> : ^^^^^^^^^^^^^^^^
>obj : T
> : ^
>{ set: deprecate( (target, property, value, receiver) => Reflect.set(target, property, value, receiver), message, code, ), defineProperty: deprecate( (target, property, descriptor) => Reflect.defineProperty(target, property, descriptor), message, code, ), deleteProperty: deprecate( (target, property) => Reflect.deleteProperty(target, property), message, code, ), setPrototypeOf: deprecate( (target, proto) => Reflect.setPrototypeOf(target, proto), message, code, ), } : { set: (target: T, property: string | symbol, value: any, receiver: any) => boolean; defineProperty: (target: T, property: string | symbol, descriptor: PropertyDescriptor) => boolean; deleteProperty: (target: T, property: string | symbol) => boolean; setPrototypeOf: (target: T, proto: object | null) => boolean; }
> : ^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
set: deprecate(
>set : (target: T, property: string | symbol, value: any, receiver: any) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^
>deprecate( (target, property, value, receiver) => Reflect.set(target, property, value, receiver), message, code, ) : (target: T, property: string | symbol, value: any, receiver: any) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^
>deprecate : <T_1 extends Function>(fn: T_1, msg: string, code?: string) => T_1
> : ^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^
(target, property, value, receiver) =>
>(target, property, value, receiver) => Reflect.set(target, property, value, receiver) : (target: T, property: string | symbol, value: any, receiver: any) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^
>target : T
> : ^
>property : string | symbol
> : ^^^^^^^^^^^^^^^
>value : any
>receiver : any
Reflect.set(target, property, value, receiver),
>Reflect.set(target, property, value, receiver) : boolean
> : ^^^^^^^
>Reflect.set : { <T_1 extends object, P extends PropertyKey>(target: T_1, propertyKey: P, value: P extends keyof T_1 ? T_1[P] : any, receiver?: any): boolean; (target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean; }
> : ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^
>Reflect : typeof Reflect
> : ^^^^^^^^^^^^^^
>set : { <T_1 extends object, P extends PropertyKey>(target: T_1, propertyKey: P, value: P extends keyof T_1 ? T_1[P] : any, receiver?: any): boolean; (target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean; }
> : ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^^
>target : T
> : ^
>property : string | symbol
> : ^^^^^^^^^^^^^^^
>value : any
>receiver : any
message,
>message : string
> : ^^^^^^
code,
>code : string
> : ^^^^^^
),
defineProperty: deprecate(
>defineProperty : (target: T, property: string | symbol, descriptor: PropertyDescriptor) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>deprecate( (target, property, descriptor) => Reflect.defineProperty(target, property, descriptor), message, code, ) : (target: T, property: string | symbol, descriptor: PropertyDescriptor) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>deprecate : <T_1 extends Function>(fn: T_1, msg: string, code?: string) => T_1
> : ^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^
(target, property, descriptor) =>
>(target, property, descriptor) => Reflect.defineProperty(target, property, descriptor) : (target: T, property: string | symbol, descriptor: PropertyDescriptor) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>target : T
> : ^
>property : string | symbol
> : ^^^^^^^^^^^^^^^
>descriptor : PropertyDescriptor
> : ^^^^^^^^^^^^^^^^^^
Reflect.defineProperty(target, property, descriptor),
>Reflect.defineProperty(target, property, descriptor) : boolean
> : ^^^^^^^
>Reflect.defineProperty : (target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor & ThisType<any>) => boolean
> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^
>Reflect : typeof Reflect
> : ^^^^^^^^^^^^^^
>defineProperty : (target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor & ThisType<any>) => boolean
> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^
>target : T
> : ^
>property : string | symbol
> : ^^^^^^^^^^^^^^^
>descriptor : PropertyDescriptor
> : ^^^^^^^^^^^^^^^^^^
message,
>message : string
> : ^^^^^^
code,
>code : string
> : ^^^^^^
),
deleteProperty: deprecate(
>deleteProperty : (target: T, property: string | symbol) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>deprecate( (target, property) => Reflect.deleteProperty(target, property), message, code, ) : (target: T, property: string | symbol) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>deprecate : <T_1 extends Function>(fn: T_1, msg: string, code?: string) => T_1
> : ^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^
(target, property) => Reflect.deleteProperty(target, property),
>(target, property) => Reflect.deleteProperty(target, property) : (target: T, property: string | symbol) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>target : T
> : ^
>property : string | symbol
> : ^^^^^^^^^^^^^^^
>Reflect.deleteProperty(target, property) : boolean
> : ^^^^^^^
>Reflect.deleteProperty : (target: object, propertyKey: PropertyKey) => boolean
> : ^ ^^ ^^ ^^ ^^^^^
>Reflect : typeof Reflect
> : ^^^^^^^^^^^^^^
>deleteProperty : (target: object, propertyKey: PropertyKey) => boolean
> : ^ ^^ ^^ ^^ ^^^^^
>target : T
> : ^
>property : string | symbol
> : ^^^^^^^^^^^^^^^
message,
>message : string
> : ^^^^^^
code,
>code : string
> : ^^^^^^
),
setPrototypeOf: deprecate(
>setPrototypeOf : (target: T, proto: object | null) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>deprecate( (target, proto) => Reflect.setPrototypeOf(target, proto), message, code, ) : (target: T, proto: object | null) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>deprecate : <T_1 extends Function>(fn: T_1, msg: string, code?: string) => T_1
> : ^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^
(target, proto) => Reflect.setPrototypeOf(target, proto),
>(target, proto) => Reflect.setPrototypeOf(target, proto) : (target: T, proto: object | null) => boolean
> : ^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>target : T
> : ^
>proto : object | null
> : ^^^^^^^^^^^^^
>Reflect.setPrototypeOf(target, proto) : boolean
> : ^^^^^^^
>Reflect.setPrototypeOf : (target: object, proto: object | null) => boolean
> : ^ ^^ ^^ ^^ ^^^^^
>Reflect : typeof Reflect
> : ^^^^^^^^^^^^^^
>setPrototypeOf : (target: object, proto: object | null) => boolean
> : ^ ^^ ^^ ^^ ^^^^^
>target : T
> : ^
>proto : object | null
> : ^^^^^^^^^^^^^
message,
>message : string
> : ^^^^^^
code,
>code : string
> : ^^^^^^
),
});
};

View File

@ -0,0 +1,37 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion4.ts] ////
=== inferenceContextualReturnTypeUnion4.ts ===
// https://github.com/microsoft/TypeScript/issues/57905
export abstract class Storage {
>Storage : Symbol(Storage, Decl(inferenceContextualReturnTypeUnion4.ts, 0, 0))
abstract get<T extends string>(): T | Promise<T>;
>get : Symbol(Storage.get, Decl(inferenceContextualReturnTypeUnion4.ts, 2, 31))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion4.ts, 3, 17))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion4.ts, 3, 17))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion4.ts, 3, 17))
}
export abstract class SyncStorage extends Storage {
>SyncStorage : Symbol(SyncStorage, Decl(inferenceContextualReturnTypeUnion4.ts, 4, 1))
>Storage : Symbol(Storage, Decl(inferenceContextualReturnTypeUnion4.ts, 0, 0))
abstract override get<T extends string>(): T;
>get : Symbol(SyncStorage.get, Decl(inferenceContextualReturnTypeUnion4.ts, 6, 51))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion4.ts, 7, 26))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion4.ts, 7, 26))
}
export abstract class ASyncStorage extends Storage {
>ASyncStorage : Symbol(ASyncStorage, Decl(inferenceContextualReturnTypeUnion4.ts, 8, 1))
>Storage : Symbol(Storage, Decl(inferenceContextualReturnTypeUnion4.ts, 0, 0))
abstract override get<T extends string>(): Promise<T>;
>get : Symbol(ASyncStorage.get, Decl(inferenceContextualReturnTypeUnion4.ts, 10, 52))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion4.ts, 11, 26))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>T : Symbol(T, Decl(inferenceContextualReturnTypeUnion4.ts, 11, 26))
}

View File

@ -0,0 +1,36 @@
//// [tests/cases/compiler/inferenceContextualReturnTypeUnion4.ts] ////
=== inferenceContextualReturnTypeUnion4.ts ===
// https://github.com/microsoft/TypeScript/issues/57905
export abstract class Storage {
>Storage : Storage
> : ^^^^^^^
abstract get<T extends string>(): T | Promise<T>;
>get : <T extends string>() => T | Promise<T>
> : ^ ^^^^^^^^^ ^^^^^^^
}
export abstract class SyncStorage extends Storage {
>SyncStorage : SyncStorage
> : ^^^^^^^^^^^
>Storage : Storage
> : ^^^^^^^
abstract override get<T extends string>(): T;
>get : <T extends string>() => T
> : ^ ^^^^^^^^^ ^^^^^^^
}
export abstract class ASyncStorage extends Storage {
>ASyncStorage : ASyncStorage
> : ^^^^^^^^^^^^
>Storage : Storage
> : ^^^^^^^
abstract override get<T extends string>(): Promise<T>;
>get : <T extends string>() => Promise<T>
> : ^ ^^^^^^^^^ ^^^^^^^
}

View File

@ -0,0 +1,19 @@
// @strict: true
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/50719
declare function useCallback1<T extends Function>(fn: T): T;
declare function ex2(callback?: (x: number) => void): void;
ex2(useCallback1((x) => {}));
declare function ex3(callback: ((x: number) => void) | 5): void;
ex3(useCallback1((x) => {}));
// https://github.com/microsoft/TypeScript/issues/41461
declare function useCallback2<T extends (...args: any[]) => any>(
callback: T,
): T;
const test: ((x: string) => void) | undefined = useCallback2((x) => {});

View File

@ -0,0 +1,35 @@
// @strict: true
// @lib: esnext, dom
// @noEmit: true
type Query = (
container: HTMLElement,
...args: any[]
) =>
| Error
| HTMLElement
| HTMLElement[]
| Promise<HTMLElement[]>
| Promise<HTMLElement>
| null;
interface Queries {
[T: string]: Query;
}
type FindByText<T extends HTMLElement = HTMLElement> = (
container: HTMLElement,
text: string,
) => Promise<T>;
declare function findByLabelText<T extends HTMLElement = HTMLElement>(
...args: Parameters<FindByText<T>>
): ReturnType<FindByText<T>>;
const queries = {
findByLabelText,
};
type MapQueries<Q extends Queries = typeof queries> = {
[P in keyof Q]: Q[P];
};

View File

@ -0,0 +1,44 @@
// @strict: true
// @lib: esnext
// @noEmit: true
declare function deprecate<T extends Function>(
fn: T,
msg: string,
code?: string,
): T;
const soonFrozenObjectDeprecation = <T extends object>(
obj: T,
name: string,
code: string,
note = "",
): T => {
const message = `${name} will be frozen in future, all modifications are deprecated.${
note && `\n${note}`
}`;
return new Proxy(obj, {
set: deprecate(
(target, property, value, receiver) =>
Reflect.set(target, property, value, receiver),
message,
code,
),
defineProperty: deprecate(
(target, property, descriptor) =>
Reflect.defineProperty(target, property, descriptor),
message,
code,
),
deleteProperty: deprecate(
(target, property) => Reflect.deleteProperty(target, property),
message,
code,
),
setPrototypeOf: deprecate(
(target, proto) => Reflect.setPrototypeOf(target, proto),
message,
code,
),
});
};

View File

@ -0,0 +1,17 @@
// @strict: true
// @lib: esnext
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/57905
export abstract class Storage {
abstract get<T extends string>(): T | Promise<T>;
}
export abstract class SyncStorage extends Storage {
abstract override get<T extends string>(): T;
}
export abstract class ASyncStorage extends Storage {
abstract override get<T extends string>(): Promise<T>;
}