Forbid contravariant inferences to conditional type branches (#30287)
This commit is contained in:
parent
281eeac249
commit
ca9566fcde
5 changed files with 218 additions and 1 deletions
|
@ -14671,7 +14671,7 @@ namespace ts {
|
|||
inferFromTypes(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target));
|
||||
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
|
||||
}
|
||||
else if (target.flags & TypeFlags.Conditional) {
|
||||
else if (target.flags & TypeFlags.Conditional && !contravariant) {
|
||||
inferFromTypes(source, getTrueTypeFromConditionalType(<ConditionalType>target));
|
||||
inferFromTypes(source, getFalseTypeFromConditionalType(<ConditionalType>target));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
//// [overloadedConstructorFixesInferencesAppropriately.ts]
|
||||
interface Box<T> {
|
||||
v: T;
|
||||
}
|
||||
|
||||
interface ErrorResult {
|
||||
readonly error: true
|
||||
}
|
||||
|
||||
interface AsyncLoaderProps<TResult extends {}> {
|
||||
readonly asyncLoad: () => Box<TResult>;
|
||||
readonly children: (result: Exclude<TResult, ErrorResult>) => string;
|
||||
}
|
||||
|
||||
class AsyncLoader<TResult extends {}> {
|
||||
constructor(props: string, context: any);
|
||||
constructor(props: AsyncLoaderProps<TResult>);
|
||||
constructor(...args: any[]) {}
|
||||
}
|
||||
|
||||
function load(): Box<{ success: true } | ErrorResult> {
|
||||
return null as any;
|
||||
}
|
||||
|
||||
new AsyncLoader({
|
||||
asyncLoad: load,
|
||||
children: result => result.success as any,
|
||||
}); // should work fine
|
||||
|
||||
|
||||
//// [overloadedConstructorFixesInferencesAppropriately.js]
|
||||
"use strict";
|
||||
var AsyncLoader = /** @class */ (function () {
|
||||
function AsyncLoader() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
}
|
||||
return AsyncLoader;
|
||||
}());
|
||||
function load() {
|
||||
return null;
|
||||
}
|
||||
new AsyncLoader({
|
||||
asyncLoad: load,
|
||||
children: function (result) { return result.success; }
|
||||
}); // should work fine
|
|
@ -0,0 +1,76 @@
|
|||
=== tests/cases/compiler/overloadedConstructorFixesInferencesAppropriately.ts ===
|
||||
interface Box<T> {
|
||||
>Box : Symbol(Box, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 0, 14))
|
||||
|
||||
v: T;
|
||||
>v : Symbol(Box.v, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 0, 18))
|
||||
>T : Symbol(T, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 0, 14))
|
||||
}
|
||||
|
||||
interface ErrorResult {
|
||||
>ErrorResult : Symbol(ErrorResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 2, 1))
|
||||
|
||||
readonly error: true
|
||||
>error : Symbol(ErrorResult.error, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 4, 23))
|
||||
}
|
||||
|
||||
interface AsyncLoaderProps<TResult extends {}> {
|
||||
>AsyncLoaderProps : Symbol(AsyncLoaderProps, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 6, 1))
|
||||
>TResult : Symbol(TResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 8, 27))
|
||||
|
||||
readonly asyncLoad: () => Box<TResult>;
|
||||
>asyncLoad : Symbol(AsyncLoaderProps.asyncLoad, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 8, 48))
|
||||
>Box : Symbol(Box, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 0, 0))
|
||||
>TResult : Symbol(TResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 8, 27))
|
||||
|
||||
readonly children: (result: Exclude<TResult, ErrorResult>) => string;
|
||||
>children : Symbol(AsyncLoaderProps.children, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 9, 43))
|
||||
>result : Symbol(result, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 10, 24))
|
||||
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
|
||||
>TResult : Symbol(TResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 8, 27))
|
||||
>ErrorResult : Symbol(ErrorResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 2, 1))
|
||||
}
|
||||
|
||||
class AsyncLoader<TResult extends {}> {
|
||||
>AsyncLoader : Symbol(AsyncLoader, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 11, 1))
|
||||
>TResult : Symbol(TResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 13, 18))
|
||||
|
||||
constructor(props: string, context: any);
|
||||
>props : Symbol(props, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 14, 16))
|
||||
>context : Symbol(context, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 14, 30))
|
||||
|
||||
constructor(props: AsyncLoaderProps<TResult>);
|
||||
>props : Symbol(props, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 15, 16))
|
||||
>AsyncLoaderProps : Symbol(AsyncLoaderProps, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 6, 1))
|
||||
>TResult : Symbol(TResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 13, 18))
|
||||
|
||||
constructor(...args: any[]) {}
|
||||
>args : Symbol(args, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 16, 16))
|
||||
}
|
||||
|
||||
function load(): Box<{ success: true } | ErrorResult> {
|
||||
>load : Symbol(load, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 17, 1))
|
||||
>Box : Symbol(Box, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 0, 0))
|
||||
>success : Symbol(success, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 19, 22))
|
||||
>ErrorResult : Symbol(ErrorResult, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 2, 1))
|
||||
|
||||
return null as any;
|
||||
}
|
||||
|
||||
new AsyncLoader({
|
||||
>AsyncLoader : Symbol(AsyncLoader, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 11, 1))
|
||||
|
||||
asyncLoad: load,
|
||||
>asyncLoad : Symbol(asyncLoad, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 23, 17))
|
||||
>load : Symbol(load, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 17, 1))
|
||||
|
||||
children: result => result.success as any,
|
||||
>children : Symbol(children, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 24, 20))
|
||||
>result : Symbol(result, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 25, 13))
|
||||
>result.success : Symbol(success, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 19, 22))
|
||||
>result : Symbol(result, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 25, 13))
|
||||
>success : Symbol(success, Decl(overloadedConstructorFixesInferencesAppropriately.ts, 19, 22))
|
||||
|
||||
}); // should work fine
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
=== tests/cases/compiler/overloadedConstructorFixesInferencesAppropriately.ts ===
|
||||
interface Box<T> {
|
||||
v: T;
|
||||
>v : T
|
||||
}
|
||||
|
||||
interface ErrorResult {
|
||||
readonly error: true
|
||||
>error : true
|
||||
>true : true
|
||||
}
|
||||
|
||||
interface AsyncLoaderProps<TResult extends {}> {
|
||||
readonly asyncLoad: () => Box<TResult>;
|
||||
>asyncLoad : () => Box<TResult>
|
||||
|
||||
readonly children: (result: Exclude<TResult, ErrorResult>) => string;
|
||||
>children : (result: Exclude<TResult, ErrorResult>) => string
|
||||
>result : Exclude<TResult, ErrorResult>
|
||||
}
|
||||
|
||||
class AsyncLoader<TResult extends {}> {
|
||||
>AsyncLoader : AsyncLoader<TResult>
|
||||
|
||||
constructor(props: string, context: any);
|
||||
>props : string
|
||||
>context : any
|
||||
|
||||
constructor(props: AsyncLoaderProps<TResult>);
|
||||
>props : AsyncLoaderProps<TResult>
|
||||
|
||||
constructor(...args: any[]) {}
|
||||
>args : any[]
|
||||
}
|
||||
|
||||
function load(): Box<{ success: true } | ErrorResult> {
|
||||
>load : () => Box<ErrorResult | { success: true; }>
|
||||
>success : true
|
||||
>true : true
|
||||
|
||||
return null as any;
|
||||
>null as any : any
|
||||
>null : null
|
||||
}
|
||||
|
||||
new AsyncLoader({
|
||||
>new AsyncLoader({ asyncLoad: load, children: result => result.success as any,}) : AsyncLoader<ErrorResult | { success: true; }>
|
||||
>AsyncLoader : typeof AsyncLoader
|
||||
>{ asyncLoad: load, children: result => result.success as any,} : { asyncLoad: () => Box<ErrorResult | { success: true; }>; children: (result: { success: true; }) => any; }
|
||||
|
||||
asyncLoad: load,
|
||||
>asyncLoad : () => Box<ErrorResult | { success: true; }>
|
||||
>load : () => Box<ErrorResult | { success: true; }>
|
||||
|
||||
children: result => result.success as any,
|
||||
>children : (result: { success: true; }) => any
|
||||
>result => result.success as any : (result: { success: true; }) => any
|
||||
>result : { success: true; }
|
||||
>result.success as any : any
|
||||
>result.success : true
|
||||
>result : { success: true; }
|
||||
>success : true
|
||||
|
||||
}); // should work fine
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// @strict: true
|
||||
interface Box<T> {
|
||||
v: T;
|
||||
}
|
||||
|
||||
interface ErrorResult {
|
||||
readonly error: true
|
||||
}
|
||||
|
||||
interface AsyncLoaderProps<TResult extends {}> {
|
||||
readonly asyncLoad: () => Box<TResult>;
|
||||
readonly children: (result: Exclude<TResult, ErrorResult>) => string;
|
||||
}
|
||||
|
||||
class AsyncLoader<TResult extends {}> {
|
||||
constructor(props: string, context: any);
|
||||
constructor(props: AsyncLoaderProps<TResult>);
|
||||
constructor(...args: any[]) {}
|
||||
}
|
||||
|
||||
function load(): Box<{ success: true } | ErrorResult> {
|
||||
return null as any;
|
||||
}
|
||||
|
||||
new AsyncLoader({
|
||||
asyncLoad: load,
|
||||
children: result => result.success as any,
|
||||
}); // should work fine
|
Loading…
Reference in a new issue