Add inference priority level for conditional types in contravariant positions (#35199)
* Add inference priority level for conditional types in contravariant positions * Accept new API baselines * Add regression tests * Accept new baselines
This commit is contained in:
parent
84c84d8dbc
commit
94d4023043
|
@ -17552,9 +17552,12 @@ namespace ts {
|
|||
inferFromTypes(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target));
|
||||
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
|
||||
}
|
||||
else if (target.flags & TypeFlags.Conditional && !contravariant) {
|
||||
else if (target.flags & TypeFlags.Conditional) {
|
||||
const savePriority = priority;
|
||||
priority |= contravariant ? InferencePriority.ContravariantConditional : 0;
|
||||
const targetTypes = [getTrueTypeFromConditionalType(<ConditionalType>target), getFalseTypeFromConditionalType(<ConditionalType>target)];
|
||||
inferToMultipleTypes(source, targetTypes, target.flags);
|
||||
priority = savePriority;
|
||||
}
|
||||
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
inferToMultipleTypes(source, (<UnionOrIntersectionType>target).types, target.flags);
|
||||
|
|
|
@ -4740,11 +4740,12 @@ namespace ts {
|
|||
HomomorphicMappedType = 1 << 1, // Reverse inference for homomorphic mapped type
|
||||
PartialHomomorphicMappedType = 1 << 2, // Partial reverse inference for homomorphic mapped type
|
||||
MappedTypeConstraint = 1 << 3, // Reverse inference for mapped type
|
||||
ReturnType = 1 << 4, // Inference made from return type of generic function
|
||||
LiteralKeyof = 1 << 5, // Inference made from a string literal to a keyof T
|
||||
NoConstraints = 1 << 6, // Don't infer from constraints of instantiable types
|
||||
AlwaysStrict = 1 << 7, // Always use strict rules for contravariant inferences
|
||||
MaxValue = 1 << 8, // Seed for inference priority tracking
|
||||
ContravariantConditional = 1 << 4, // Conditional type in contravariant position
|
||||
ReturnType = 1 << 5, // Inference made from return type of generic function
|
||||
LiteralKeyof = 1 << 6, // Inference made from a string literal to a keyof T
|
||||
NoConstraints = 1 << 7, // Don't infer from constraints of instantiable types
|
||||
AlwaysStrict = 1 << 8, // Always use strict rules for contravariant inferences
|
||||
MaxValue = 1 << 9, // Seed for inference priority tracking
|
||||
|
||||
PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates
|
||||
Circularity = -1, // Inference circularity (value less than all other priorities)
|
||||
|
|
|
@ -2500,12 +2500,13 @@ declare namespace ts {
|
|||
HomomorphicMappedType = 2,
|
||||
PartialHomomorphicMappedType = 4,
|
||||
MappedTypeConstraint = 8,
|
||||
ReturnType = 16,
|
||||
LiteralKeyof = 32,
|
||||
NoConstraints = 64,
|
||||
AlwaysStrict = 128,
|
||||
MaxValue = 256,
|
||||
PriorityImpliesCombination = 56,
|
||||
ContravariantConditional = 16,
|
||||
ReturnType = 32,
|
||||
LiteralKeyof = 64,
|
||||
NoConstraints = 128,
|
||||
AlwaysStrict = 256,
|
||||
MaxValue = 512,
|
||||
PriorityImpliesCombination = 104,
|
||||
Circularity = -1
|
||||
}
|
||||
/** @deprecated Use FileExtensionInfo instead. */
|
||||
|
|
13
tests/baselines/reference/api/typescript.d.ts
vendored
13
tests/baselines/reference/api/typescript.d.ts
vendored
|
@ -2500,12 +2500,13 @@ declare namespace ts {
|
|||
HomomorphicMappedType = 2,
|
||||
PartialHomomorphicMappedType = 4,
|
||||
MappedTypeConstraint = 8,
|
||||
ReturnType = 16,
|
||||
LiteralKeyof = 32,
|
||||
NoConstraints = 64,
|
||||
AlwaysStrict = 128,
|
||||
MaxValue = 256,
|
||||
PriorityImpliesCombination = 56,
|
||||
ContravariantConditional = 16,
|
||||
ReturnType = 32,
|
||||
LiteralKeyof = 64,
|
||||
NoConstraints = 128,
|
||||
AlwaysStrict = 256,
|
||||
MaxValue = 512,
|
||||
PriorityImpliesCombination = 104,
|
||||
Circularity = -1
|
||||
}
|
||||
/** @deprecated Use FileExtensionInfo instead. */
|
||||
|
|
|
@ -273,4 +273,47 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
|
|||
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
|
||||
type What = Hmm<{}, { a: string }>
|
||||
const w: What = { a: 4 };
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function save(_response: IRootResponse<string>): void;
|
||||
|
||||
exportCommand(save);
|
||||
|
||||
declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void;
|
||||
|
||||
interface IExportCallback<TResponse> {
|
||||
(response: IRootResponse<TResponse>): void;
|
||||
}
|
||||
|
||||
type IRootResponse<TResponse> =
|
||||
TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>;
|
||||
|
||||
interface IRecord {
|
||||
readonly Id: string;
|
||||
}
|
||||
|
||||
declare type IRecordResponse<T extends IRecord> = IResponse<T> & {
|
||||
sendRecord(): void;
|
||||
};
|
||||
|
||||
declare type IResponse<T> = {
|
||||
sendValue(name: keyof GetAllPropertiesOfType<T, string>): void;
|
||||
};
|
||||
|
||||
declare type GetPropertyNamesOfType<T, RestrictToType> = {
|
||||
[PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never
|
||||
}[Extract<keyof T, string>];
|
||||
|
||||
declare type GetAllPropertiesOfType<T, RestrictToType> = Pick<
|
||||
T,
|
||||
GetPropertyNamesOfType<Required<T>, RestrictToType>
|
||||
>;
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function ff(x: Foo3<string>): void;
|
||||
declare function gg<T>(f: (x: Foo3<T>) => void): void;
|
||||
type Foo3<T> = T extends number ? { n: T } : { x: T };
|
||||
gg(ff);
|
||||
|
|
@ -194,6 +194,49 @@ type PCCB = ProductComplementComplement['b'];
|
|||
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
|
||||
type What = Hmm<{}, { a: string }>
|
||||
const w: What = { a: 4 };
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function save(_response: IRootResponse<string>): void;
|
||||
|
||||
exportCommand(save);
|
||||
|
||||
declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void;
|
||||
|
||||
interface IExportCallback<TResponse> {
|
||||
(response: IRootResponse<TResponse>): void;
|
||||
}
|
||||
|
||||
type IRootResponse<TResponse> =
|
||||
TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>;
|
||||
|
||||
interface IRecord {
|
||||
readonly Id: string;
|
||||
}
|
||||
|
||||
declare type IRecordResponse<T extends IRecord> = IResponse<T> & {
|
||||
sendRecord(): void;
|
||||
};
|
||||
|
||||
declare type IResponse<T> = {
|
||||
sendValue(name: keyof GetAllPropertiesOfType<T, string>): void;
|
||||
};
|
||||
|
||||
declare type GetPropertyNamesOfType<T, RestrictToType> = {
|
||||
[PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never
|
||||
}[Extract<keyof T, string>];
|
||||
|
||||
declare type GetAllPropertiesOfType<T, RestrictToType> = Pick<
|
||||
T,
|
||||
GetPropertyNamesOfType<Required<T>, RestrictToType>
|
||||
>;
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function ff(x: Foo3<string>): void;
|
||||
declare function gg<T>(f: (x: Foo3<T>) => void): void;
|
||||
type Foo3<T> = T extends number ? { n: T } : { x: T };
|
||||
gg(ff);
|
||||
|
||||
|
||||
//// [conditionalTypes2.js]
|
||||
|
@ -272,6 +315,8 @@ function foo(value) {
|
|||
}
|
||||
}
|
||||
var w = { a: 4 };
|
||||
exportCommand(save);
|
||||
gg(ff);
|
||||
|
||||
|
||||
//// [conditionalTypes2.d.ts]
|
||||
|
@ -406,3 +451,29 @@ declare type What = Hmm<{}, {
|
|||
a: string;
|
||||
}>;
|
||||
declare const w: What;
|
||||
declare function save(_response: IRootResponse<string>): void;
|
||||
declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void;
|
||||
interface IExportCallback<TResponse> {
|
||||
(response: IRootResponse<TResponse>): void;
|
||||
}
|
||||
declare type IRootResponse<TResponse> = TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>;
|
||||
interface IRecord {
|
||||
readonly Id: string;
|
||||
}
|
||||
declare type IRecordResponse<T extends IRecord> = IResponse<T> & {
|
||||
sendRecord(): void;
|
||||
};
|
||||
declare type IResponse<T> = {
|
||||
sendValue(name: keyof GetAllPropertiesOfType<T, string>): void;
|
||||
};
|
||||
declare type GetPropertyNamesOfType<T, RestrictToType> = {
|
||||
[PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never;
|
||||
}[Extract<keyof T, string>];
|
||||
declare type GetAllPropertiesOfType<T, RestrictToType> = Pick<T, GetPropertyNamesOfType<Required<T>, RestrictToType>>;
|
||||
declare function ff(x: Foo3<string>): void;
|
||||
declare function gg<T>(f: (x: Foo3<T>) => void): void;
|
||||
declare type Foo3<T> = T extends number ? {
|
||||
n: T;
|
||||
} : {
|
||||
x: T;
|
||||
};
|
||||
|
|
|
@ -707,3 +707,137 @@ const w: What = { a: 4 };
|
|||
>What : Symbol(What, Decl(conditionalTypes2.ts, 192, 76))
|
||||
>a : Symbol(a, Decl(conditionalTypes2.ts, 194, 17))
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function save(_response: IRootResponse<string>): void;
|
||||
>save : Symbol(save, Decl(conditionalTypes2.ts, 194, 25))
|
||||
>_response : Symbol(_response, Decl(conditionalTypes2.ts, 198, 22))
|
||||
>IRootResponse : Symbol(IRootResponse, Decl(conditionalTypes2.ts, 206, 1))
|
||||
|
||||
exportCommand(save);
|
||||
>exportCommand : Symbol(exportCommand, Decl(conditionalTypes2.ts, 200, 20))
|
||||
>save : Symbol(save, Decl(conditionalTypes2.ts, 194, 25))
|
||||
|
||||
declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void;
|
||||
>exportCommand : Symbol(exportCommand, Decl(conditionalTypes2.ts, 200, 20))
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 202, 31))
|
||||
>functionToCall : Symbol(functionToCall, Decl(conditionalTypes2.ts, 202, 42))
|
||||
>IExportCallback : Symbol(IExportCallback, Decl(conditionalTypes2.ts, 202, 92))
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 202, 31))
|
||||
|
||||
interface IExportCallback<TResponse> {
|
||||
>IExportCallback : Symbol(IExportCallback, Decl(conditionalTypes2.ts, 202, 92))
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 204, 26))
|
||||
|
||||
(response: IRootResponse<TResponse>): void;
|
||||
>response : Symbol(response, Decl(conditionalTypes2.ts, 205, 2))
|
||||
>IRootResponse : Symbol(IRootResponse, Decl(conditionalTypes2.ts, 206, 1))
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 204, 26))
|
||||
}
|
||||
|
||||
type IRootResponse<TResponse> =
|
||||
>IRootResponse : Symbol(IRootResponse, Decl(conditionalTypes2.ts, 206, 1))
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 208, 19))
|
||||
|
||||
TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>;
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 208, 19))
|
||||
>IRecord : Symbol(IRecord, Decl(conditionalTypes2.ts, 209, 79))
|
||||
>IRecordResponse : Symbol(IRecordResponse, Decl(conditionalTypes2.ts, 213, 1))
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 208, 19))
|
||||
>IResponse : Symbol(IResponse, Decl(conditionalTypes2.ts, 217, 2))
|
||||
>TResponse : Symbol(TResponse, Decl(conditionalTypes2.ts, 208, 19))
|
||||
|
||||
interface IRecord {
|
||||
>IRecord : Symbol(IRecord, Decl(conditionalTypes2.ts, 209, 79))
|
||||
|
||||
readonly Id: string;
|
||||
>Id : Symbol(IRecord.Id, Decl(conditionalTypes2.ts, 211, 19))
|
||||
}
|
||||
|
||||
declare type IRecordResponse<T extends IRecord> = IResponse<T> & {
|
||||
>IRecordResponse : Symbol(IRecordResponse, Decl(conditionalTypes2.ts, 213, 1))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 215, 29))
|
||||
>IRecord : Symbol(IRecord, Decl(conditionalTypes2.ts, 209, 79))
|
||||
>IResponse : Symbol(IResponse, Decl(conditionalTypes2.ts, 217, 2))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 215, 29))
|
||||
|
||||
sendRecord(): void;
|
||||
>sendRecord : Symbol(sendRecord, Decl(conditionalTypes2.ts, 215, 66))
|
||||
|
||||
};
|
||||
|
||||
declare type IResponse<T> = {
|
||||
>IResponse : Symbol(IResponse, Decl(conditionalTypes2.ts, 217, 2))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 219, 23))
|
||||
|
||||
sendValue(name: keyof GetAllPropertiesOfType<T, string>): void;
|
||||
>sendValue : Symbol(sendValue, Decl(conditionalTypes2.ts, 219, 29))
|
||||
>name : Symbol(name, Decl(conditionalTypes2.ts, 220, 11))
|
||||
>GetAllPropertiesOfType : Symbol(GetAllPropertiesOfType, Decl(conditionalTypes2.ts, 225, 28))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 219, 23))
|
||||
|
||||
};
|
||||
|
||||
declare type GetPropertyNamesOfType<T, RestrictToType> = {
|
||||
>GetPropertyNamesOfType : Symbol(GetPropertyNamesOfType, Decl(conditionalTypes2.ts, 221, 2))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 223, 36))
|
||||
>RestrictToType : Symbol(RestrictToType, Decl(conditionalTypes2.ts, 223, 38))
|
||||
|
||||
[PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never
|
||||
>PropertyName : Symbol(PropertyName, Decl(conditionalTypes2.ts, 224, 2))
|
||||
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 223, 36))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 223, 36))
|
||||
>PropertyName : Symbol(PropertyName, Decl(conditionalTypes2.ts, 224, 2))
|
||||
>RestrictToType : Symbol(RestrictToType, Decl(conditionalTypes2.ts, 223, 38))
|
||||
>PropertyName : Symbol(PropertyName, Decl(conditionalTypes2.ts, 224, 2))
|
||||
|
||||
}[Extract<keyof T, string>];
|
||||
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 223, 36))
|
||||
|
||||
declare type GetAllPropertiesOfType<T, RestrictToType> = Pick<
|
||||
>GetAllPropertiesOfType : Symbol(GetAllPropertiesOfType, Decl(conditionalTypes2.ts, 225, 28))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 227, 36))
|
||||
>RestrictToType : Symbol(RestrictToType, Decl(conditionalTypes2.ts, 227, 38))
|
||||
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
T,
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 227, 36))
|
||||
|
||||
GetPropertyNamesOfType<Required<T>, RestrictToType>
|
||||
>GetPropertyNamesOfType : Symbol(GetPropertyNamesOfType, Decl(conditionalTypes2.ts, 221, 2))
|
||||
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 227, 36))
|
||||
>RestrictToType : Symbol(RestrictToType, Decl(conditionalTypes2.ts, 227, 38))
|
||||
|
||||
>;
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function ff(x: Foo3<string>): void;
|
||||
>ff : Symbol(ff, Decl(conditionalTypes2.ts, 230, 2))
|
||||
>x : Symbol(x, Decl(conditionalTypes2.ts, 234, 20))
|
||||
>Foo3 : Symbol(Foo3, Decl(conditionalTypes2.ts, 235, 54))
|
||||
|
||||
declare function gg<T>(f: (x: Foo3<T>) => void): void;
|
||||
>gg : Symbol(gg, Decl(conditionalTypes2.ts, 234, 43))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 235, 20))
|
||||
>f : Symbol(f, Decl(conditionalTypes2.ts, 235, 23))
|
||||
>x : Symbol(x, Decl(conditionalTypes2.ts, 235, 27))
|
||||
>Foo3 : Symbol(Foo3, Decl(conditionalTypes2.ts, 235, 54))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 235, 20))
|
||||
|
||||
type Foo3<T> = T extends number ? { n: T } : { x: T };
|
||||
>Foo3 : Symbol(Foo3, Decl(conditionalTypes2.ts, 235, 54))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 236, 10))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 236, 10))
|
||||
>n : Symbol(n, Decl(conditionalTypes2.ts, 236, 35))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 236, 10))
|
||||
>x : Symbol(x, Decl(conditionalTypes2.ts, 236, 46))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 236, 10))
|
||||
|
||||
gg(ff);
|
||||
>gg : Symbol(gg, Decl(conditionalTypes2.ts, 234, 43))
|
||||
>ff : Symbol(ff, Decl(conditionalTypes2.ts, 230, 2))
|
||||
|
||||
|
|
|
@ -446,3 +446,84 @@ const w: What = { a: 4 };
|
|||
>a : number
|
||||
>4 : 4
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function save(_response: IRootResponse<string>): void;
|
||||
>save : (_response: IResponse<string>) => void
|
||||
>_response : IResponse<string>
|
||||
|
||||
exportCommand(save);
|
||||
>exportCommand(save) : void
|
||||
>exportCommand : <TResponse>(functionToCall: IExportCallback<TResponse>) => void
|
||||
>save : (_response: IResponse<string>) => void
|
||||
|
||||
declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void;
|
||||
>exportCommand : <TResponse>(functionToCall: IExportCallback<TResponse>) => void
|
||||
>functionToCall : IExportCallback<TResponse>
|
||||
|
||||
interface IExportCallback<TResponse> {
|
||||
(response: IRootResponse<TResponse>): void;
|
||||
>response : IRootResponse<TResponse>
|
||||
}
|
||||
|
||||
type IRootResponse<TResponse> =
|
||||
>IRootResponse : IRootResponse<TResponse>
|
||||
|
||||
TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>;
|
||||
|
||||
interface IRecord {
|
||||
readonly Id: string;
|
||||
>Id : string
|
||||
}
|
||||
|
||||
declare type IRecordResponse<T extends IRecord> = IResponse<T> & {
|
||||
>IRecordResponse : IRecordResponse<T>
|
||||
|
||||
sendRecord(): void;
|
||||
>sendRecord : () => void
|
||||
|
||||
};
|
||||
|
||||
declare type IResponse<T> = {
|
||||
>IResponse : IResponse<T>
|
||||
|
||||
sendValue(name: keyof GetAllPropertiesOfType<T, string>): void;
|
||||
>sendValue : (name: { [PropertyName in Extract<keyof T, string>]: Required<T>[PropertyName] extends string ? PropertyName : never; }[Extract<keyof T, string>]) => void
|
||||
>name : { [PropertyName in Extract<keyof T, string>]: Required<T>[PropertyName] extends string ? PropertyName : never; }[Extract<keyof T, string>]
|
||||
|
||||
};
|
||||
|
||||
declare type GetPropertyNamesOfType<T, RestrictToType> = {
|
||||
>GetPropertyNamesOfType : { [PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never; }[Extract<keyof T, string>]
|
||||
|
||||
[PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never
|
||||
}[Extract<keyof T, string>];
|
||||
|
||||
declare type GetAllPropertiesOfType<T, RestrictToType> = Pick<
|
||||
>GetAllPropertiesOfType : Pick<T, { [PropertyName in Extract<keyof T, string>]: Required<T>[PropertyName] extends RestrictToType ? PropertyName : never; }[Extract<keyof T, string>]>
|
||||
|
||||
T,
|
||||
GetPropertyNamesOfType<Required<T>, RestrictToType>
|
||||
>;
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function ff(x: Foo3<string>): void;
|
||||
>ff : (x: { x: string; }) => void
|
||||
>x : { x: string; }
|
||||
|
||||
declare function gg<T>(f: (x: Foo3<T>) => void): void;
|
||||
>gg : <T>(f: (x: Foo3<T>) => void) => void
|
||||
>f : (x: Foo3<T>) => void
|
||||
>x : Foo3<T>
|
||||
|
||||
type Foo3<T> = T extends number ? { n: T } : { x: T };
|
||||
>Foo3 : Foo3<T>
|
||||
>n : T
|
||||
>x : T
|
||||
|
||||
gg(ff);
|
||||
>gg(ff) : void
|
||||
>gg : <T>(f: (x: Foo3<T>) => void) => void
|
||||
>ff : (x: { x: string; }) => void
|
||||
|
||||
|
|
|
@ -196,3 +196,46 @@ type PCCB = ProductComplementComplement['b'];
|
|||
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
|
||||
type What = Hmm<{}, { a: string }>
|
||||
const w: What = { a: 4 };
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function save(_response: IRootResponse<string>): void;
|
||||
|
||||
exportCommand(save);
|
||||
|
||||
declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void;
|
||||
|
||||
interface IExportCallback<TResponse> {
|
||||
(response: IRootResponse<TResponse>): void;
|
||||
}
|
||||
|
||||
type IRootResponse<TResponse> =
|
||||
TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>;
|
||||
|
||||
interface IRecord {
|
||||
readonly Id: string;
|
||||
}
|
||||
|
||||
declare type IRecordResponse<T extends IRecord> = IResponse<T> & {
|
||||
sendRecord(): void;
|
||||
};
|
||||
|
||||
declare type IResponse<T> = {
|
||||
sendValue(name: keyof GetAllPropertiesOfType<T, string>): void;
|
||||
};
|
||||
|
||||
declare type GetPropertyNamesOfType<T, RestrictToType> = {
|
||||
[PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never
|
||||
}[Extract<keyof T, string>];
|
||||
|
||||
declare type GetAllPropertiesOfType<T, RestrictToType> = Pick<
|
||||
T,
|
||||
GetPropertyNamesOfType<Required<T>, RestrictToType>
|
||||
>;
|
||||
|
||||
// Repro from #33568
|
||||
|
||||
declare function ff(x: Foo3<string>): void;
|
||||
declare function gg<T>(f: (x: Foo3<T>) => void): void;
|
||||
type Foo3<T> = T extends number ? { n: T } : { x: T };
|
||||
gg(ff);
|
||||
|
|
Loading…
Reference in a new issue