mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
No contextual typing from return types for boolean literals (#48380)
* No contextual typing from return types for boolean literals * Accept new baselines * Add regression tests
This commit is contained in:
parent
e62f960648
commit
3f483d87b4
@ -26902,9 +26902,14 @@ namespace ts {
|
||||
return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper);
|
||||
}
|
||||
// For other purposes (e.g. determining whether to produce literal types) we only
|
||||
// incorporate inferences made from the return type in a function call.
|
||||
// incorporate inferences made from the return type in a function call. We remove
|
||||
// the 'boolean' type from the contextual type such that contextually typed boolean
|
||||
// literals actually end up widening to 'boolean' (see #48363).
|
||||
if (inferenceContext.returnMapper) {
|
||||
return instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper);
|
||||
const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper);
|
||||
return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ?
|
||||
filterType(type, t => t !== regularFalseType && t !== regularTrueType) :
|
||||
type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
//// [contextuallyTypedBooleanLiterals.ts]
|
||||
// Repro from #48363
|
||||
|
||||
type Box<T> = {
|
||||
get: () => T,
|
||||
set: (value: T) => void
|
||||
}
|
||||
|
||||
declare function box<T>(value: T): Box<T>;
|
||||
|
||||
const bn1 = box(0); // Box<number>
|
||||
const bn2: Box<number> = box(0); // Ok
|
||||
|
||||
const bb1 = box(false); // Box<boolean>
|
||||
const bb2: Box<boolean> = box(false); // Error, box<false> not assignable to Box<boolean>
|
||||
|
||||
// Repro from #48150
|
||||
|
||||
interface Observable<T>
|
||||
{
|
||||
(): T;
|
||||
(value: T): any;
|
||||
}
|
||||
|
||||
declare function observable<T>(value: T): Observable<T>;
|
||||
|
||||
const x: Observable<boolean> = observable(false);
|
||||
|
||||
|
||||
//// [contextuallyTypedBooleanLiterals.js]
|
||||
"use strict";
|
||||
// Repro from #48363
|
||||
var bn1 = box(0); // Box<number>
|
||||
var bn2 = box(0); // Ok
|
||||
var bb1 = box(false); // Box<boolean>
|
||||
var bb2 = box(false); // Error, box<false> not assignable to Box<boolean>
|
||||
var x = observable(false);
|
||||
|
||||
|
||||
//// [contextuallyTypedBooleanLiterals.d.ts]
|
||||
declare type Box<T> = {
|
||||
get: () => T;
|
||||
set: (value: T) => void;
|
||||
};
|
||||
declare function box<T>(value: T): Box<T>;
|
||||
declare const bn1: Box<number>;
|
||||
declare const bn2: Box<number>;
|
||||
declare const bb1: Box<boolean>;
|
||||
declare const bb2: Box<boolean>;
|
||||
interface Observable<T> {
|
||||
(): T;
|
||||
(value: T): any;
|
||||
}
|
||||
declare function observable<T>(value: T): Observable<T>;
|
||||
declare const x: Observable<boolean>;
|
||||
@ -0,0 +1,70 @@
|
||||
=== tests/cases/compiler/contextuallyTypedBooleanLiterals.ts ===
|
||||
// Repro from #48363
|
||||
|
||||
type Box<T> = {
|
||||
>Box : Symbol(Box, Decl(contextuallyTypedBooleanLiterals.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 2, 9))
|
||||
|
||||
get: () => T,
|
||||
>get : Symbol(get, Decl(contextuallyTypedBooleanLiterals.ts, 2, 15))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 2, 9))
|
||||
|
||||
set: (value: T) => void
|
||||
>set : Symbol(set, Decl(contextuallyTypedBooleanLiterals.ts, 3, 17))
|
||||
>value : Symbol(value, Decl(contextuallyTypedBooleanLiterals.ts, 4, 10))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 2, 9))
|
||||
}
|
||||
|
||||
declare function box<T>(value: T): Box<T>;
|
||||
>box : Symbol(box, Decl(contextuallyTypedBooleanLiterals.ts, 5, 1))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 7, 21))
|
||||
>value : Symbol(value, Decl(contextuallyTypedBooleanLiterals.ts, 7, 24))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 7, 21))
|
||||
>Box : Symbol(Box, Decl(contextuallyTypedBooleanLiterals.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 7, 21))
|
||||
|
||||
const bn1 = box(0); // Box<number>
|
||||
>bn1 : Symbol(bn1, Decl(contextuallyTypedBooleanLiterals.ts, 9, 5))
|
||||
>box : Symbol(box, Decl(contextuallyTypedBooleanLiterals.ts, 5, 1))
|
||||
|
||||
const bn2: Box<number> = box(0); // Ok
|
||||
>bn2 : Symbol(bn2, Decl(contextuallyTypedBooleanLiterals.ts, 10, 5))
|
||||
>Box : Symbol(Box, Decl(contextuallyTypedBooleanLiterals.ts, 0, 0))
|
||||
>box : Symbol(box, Decl(contextuallyTypedBooleanLiterals.ts, 5, 1))
|
||||
|
||||
const bb1 = box(false); // Box<boolean>
|
||||
>bb1 : Symbol(bb1, Decl(contextuallyTypedBooleanLiterals.ts, 12, 5))
|
||||
>box : Symbol(box, Decl(contextuallyTypedBooleanLiterals.ts, 5, 1))
|
||||
|
||||
const bb2: Box<boolean> = box(false); // Error, box<false> not assignable to Box<boolean>
|
||||
>bb2 : Symbol(bb2, Decl(contextuallyTypedBooleanLiterals.ts, 13, 5))
|
||||
>Box : Symbol(Box, Decl(contextuallyTypedBooleanLiterals.ts, 0, 0))
|
||||
>box : Symbol(box, Decl(contextuallyTypedBooleanLiterals.ts, 5, 1))
|
||||
|
||||
// Repro from #48150
|
||||
|
||||
interface Observable<T>
|
||||
>Observable : Symbol(Observable, Decl(contextuallyTypedBooleanLiterals.ts, 13, 37))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 17, 21))
|
||||
{
|
||||
(): T;
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 17, 21))
|
||||
|
||||
(value: T): any;
|
||||
>value : Symbol(value, Decl(contextuallyTypedBooleanLiterals.ts, 20, 3))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 17, 21))
|
||||
}
|
||||
|
||||
declare function observable<T>(value: T): Observable<T>;
|
||||
>observable : Symbol(observable, Decl(contextuallyTypedBooleanLiterals.ts, 21, 1))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 23, 28))
|
||||
>value : Symbol(value, Decl(contextuallyTypedBooleanLiterals.ts, 23, 31))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 23, 28))
|
||||
>Observable : Symbol(Observable, Decl(contextuallyTypedBooleanLiterals.ts, 13, 37))
|
||||
>T : Symbol(T, Decl(contextuallyTypedBooleanLiterals.ts, 23, 28))
|
||||
|
||||
const x: Observable<boolean> = observable(false);
|
||||
>x : Symbol(x, Decl(contextuallyTypedBooleanLiterals.ts, 25, 5))
|
||||
>Observable : Symbol(Observable, Decl(contextuallyTypedBooleanLiterals.ts, 13, 37))
|
||||
>observable : Symbol(observable, Decl(contextuallyTypedBooleanLiterals.ts, 21, 1))
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
=== tests/cases/compiler/contextuallyTypedBooleanLiterals.ts ===
|
||||
// Repro from #48363
|
||||
|
||||
type Box<T> = {
|
||||
>Box : Box<T>
|
||||
|
||||
get: () => T,
|
||||
>get : () => T
|
||||
|
||||
set: (value: T) => void
|
||||
>set : (value: T) => void
|
||||
>value : T
|
||||
}
|
||||
|
||||
declare function box<T>(value: T): Box<T>;
|
||||
>box : <T>(value: T) => Box<T>
|
||||
>value : T
|
||||
|
||||
const bn1 = box(0); // Box<number>
|
||||
>bn1 : Box<number>
|
||||
>box(0) : Box<number>
|
||||
>box : <T>(value: T) => Box<T>
|
||||
>0 : 0
|
||||
|
||||
const bn2: Box<number> = box(0); // Ok
|
||||
>bn2 : Box<number>
|
||||
>box(0) : Box<number>
|
||||
>box : <T>(value: T) => Box<T>
|
||||
>0 : 0
|
||||
|
||||
const bb1 = box(false); // Box<boolean>
|
||||
>bb1 : Box<boolean>
|
||||
>box(false) : Box<boolean>
|
||||
>box : <T>(value: T) => Box<T>
|
||||
>false : false
|
||||
|
||||
const bb2: Box<boolean> = box(false); // Error, box<false> not assignable to Box<boolean>
|
||||
>bb2 : Box<boolean>
|
||||
>box(false) : Box<boolean>
|
||||
>box : <T>(value: T) => Box<T>
|
||||
>false : false
|
||||
|
||||
// Repro from #48150
|
||||
|
||||
interface Observable<T>
|
||||
{
|
||||
(): T;
|
||||
(value: T): any;
|
||||
>value : T
|
||||
}
|
||||
|
||||
declare function observable<T>(value: T): Observable<T>;
|
||||
>observable : <T>(value: T) => Observable<T>
|
||||
>value : T
|
||||
|
||||
const x: Observable<boolean> = observable(false);
|
||||
>x : Observable<boolean>
|
||||
>observable(false) : Observable<boolean>
|
||||
>observable : <T>(value: T) => Observable<T>
|
||||
>false : false
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(28,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"bar"'.
|
||||
tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(175,47): error TS2322: Type 'boolean' is not assignable to type 'true'.
|
||||
tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(180,26): error TS2322: Type '{ state: State.A; }[] | { state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'.
|
||||
Type '{ state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'.
|
||||
Type '{ state: State.B; }' is not assignable to type '{ state: State.A; }'.
|
||||
@ -7,7 +6,7 @@ tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(180,26): error TS23
|
||||
Type 'State.B' is not assignable to type 'State.A'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (3 errors) ====
|
||||
==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (2 errors) ====
|
||||
// Repros from #5487
|
||||
|
||||
function truePromise(): Promise<true> {
|
||||
@ -185,9 +184,6 @@ tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(180,26): error TS23
|
||||
|
||||
declare function foldLeft<U>(z: U, f: (acc: U, t: boolean) => U): U;
|
||||
let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type 'boolean' is not assignable to type 'true'.
|
||||
!!! related TS6502 tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts:174:39: The expected type comes from the return type of this signature.
|
||||
|
||||
enum State { A, B }
|
||||
type Foo = { state: State }
|
||||
|
||||
@ -461,14 +461,14 @@ declare function foldLeft<U>(z: U, f: (acc: U, t: boolean) => U): U;
|
||||
|
||||
let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error
|
||||
>res : boolean
|
||||
>foldLeft(true, (acc, t) => acc && t) : true
|
||||
>foldLeft(true, (acc, t) => acc && t) : boolean
|
||||
>foldLeft : <U>(z: U, f: (acc: U, t: boolean) => U) => U
|
||||
>true : true
|
||||
>(acc, t) => acc && t : (acc: true, t: boolean) => boolean
|
||||
>acc : true
|
||||
>(acc, t) => acc && t : (acc: boolean, t: boolean) => boolean
|
||||
>acc : boolean
|
||||
>t : boolean
|
||||
>acc && t : boolean
|
||||
>acc : true
|
||||
>acc : boolean
|
||||
>t : boolean
|
||||
|
||||
enum State { A, B }
|
||||
|
||||
32
tests/cases/compiler/contextuallyTypedBooleanLiterals.ts
Normal file
32
tests/cases/compiler/contextuallyTypedBooleanLiterals.ts
Normal file
@ -0,0 +1,32 @@
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
// Repro from #48363
|
||||
|
||||
type Box<T> = {
|
||||
get: () => T,
|
||||
set: (value: T) => void
|
||||
}
|
||||
|
||||
declare function box<T>(value: T): Box<T>;
|
||||
|
||||
const bn1 = box(0); // Box<number>
|
||||
const bn2: Box<number> = box(0); // Ok
|
||||
|
||||
const bb1 = box(false); // Box<boolean>
|
||||
const bb2: Box<boolean> = box(false); // Error, box<false> not assignable to Box<boolean>
|
||||
|
||||
// Repro from #48150
|
||||
|
||||
interface Observable<T>
|
||||
{
|
||||
(): T;
|
||||
(value: T): any;
|
||||
}
|
||||
|
||||
declare function observable<T>(value: T): Observable<T>;
|
||||
|
||||
const x: Observable<boolean> = observable(false);
|
||||
Loading…
x
Reference in New Issue
Block a user