Add narrowing for unknown with strict equal
This commit is contained in:
parent
d16cf761ba
commit
267e5989cd
|
@ -16018,6 +16018,9 @@ namespace ts {
|
|||
assumeTrue = !assumeTrue;
|
||||
}
|
||||
const valueType = getTypeOfExpression(value);
|
||||
if ((type.flags & TypeFlags.Unknown) && (operator === SyntaxKind.EqualsEqualsEqualsToken) && (valueType.flags & TypeFlags.Unit)) {
|
||||
return assumeTrue ? valueType : type;
|
||||
}
|
||||
if (valueType.flags & TypeFlags.Nullable) {
|
||||
if (!strictNullChecks) {
|
||||
return type;
|
||||
|
|
82
tests/baselines/reference/unknownType2.js
Normal file
82
tests/baselines/reference/unknownType2.js
Normal file
|
@ -0,0 +1,82 @@
|
|||
//// [unknownType2.ts]
|
||||
type isUnknown<T> = unknown extends T ? true : false;
|
||||
type isTrue<T extends true> = T;
|
||||
|
||||
type SomeResponse = 'yes' | 'no' | 'idk';
|
||||
let validate: (x: unknown) => SomeResponse = x => (x === 'yes' || x === 'no') ? x : 'idk'; // No error
|
||||
|
||||
const u: unknown = undefined;
|
||||
|
||||
declare const symb: unique symbol;
|
||||
|
||||
if (u === 5) {
|
||||
const y = u.toString(10);
|
||||
}
|
||||
|
||||
if (u === true || u === false) {
|
||||
const someBool: boolean = u;
|
||||
}
|
||||
|
||||
if (u === undefined) {
|
||||
const undef: undefined = u;
|
||||
}
|
||||
|
||||
if (u === null) {
|
||||
const someNull: null = u;
|
||||
}
|
||||
|
||||
if(u === symb) {
|
||||
const symbolAlias: typeof symb = u;
|
||||
}
|
||||
|
||||
if (!(u === 42)) {
|
||||
u // u should still be `unknown` here
|
||||
}
|
||||
|
||||
if (u !== 42) {
|
||||
type A = isTrue<isUnknown<typeof u>>
|
||||
}
|
||||
|
||||
if (u == 42) {
|
||||
type B = isTrue<isUnknown<typeof u>>
|
||||
}
|
||||
|
||||
if (u == true) {
|
||||
type C = isTrue<isUnknown<typeof u>>
|
||||
}
|
||||
|
||||
if (u == Object) {
|
||||
type D = isTrue<isUnknown<typeof u>>
|
||||
}
|
||||
|
||||
|
||||
//// [unknownType2.js]
|
||||
"use strict";
|
||||
var validate = function (x) { return (x === 'yes' || x === 'no') ? x : 'idk'; }; // No error
|
||||
var u = undefined;
|
||||
if (u === 5) {
|
||||
var y = u.toString(10);
|
||||
}
|
||||
if (u === true || u === false) {
|
||||
var someBool = u;
|
||||
}
|
||||
if (u === undefined) {
|
||||
var undef = u;
|
||||
}
|
||||
if (u === null) {
|
||||
var someNull = u;
|
||||
}
|
||||
if (u === symb) {
|
||||
var symbolAlias = u;
|
||||
}
|
||||
if (!(u === 42)) {
|
||||
u; // u should still be `unknown` here
|
||||
}
|
||||
if (u !== 42) {
|
||||
}
|
||||
if (u == 42) {
|
||||
}
|
||||
if (u == true) {
|
||||
}
|
||||
if (u == Object) {
|
||||
}
|
124
tests/baselines/reference/unknownType2.symbols
Normal file
124
tests/baselines/reference/unknownType2.symbols
Normal file
|
@ -0,0 +1,124 @@
|
|||
=== tests/cases/conformance/types/unknown/unknownType2.ts ===
|
||||
type isUnknown<T> = unknown extends T ? true : false;
|
||||
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(unknownType2.ts, 0, 15))
|
||||
>T : Symbol(T, Decl(unknownType2.ts, 0, 15))
|
||||
|
||||
type isTrue<T extends true> = T;
|
||||
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
|
||||
>T : Symbol(T, Decl(unknownType2.ts, 1, 12))
|
||||
>T : Symbol(T, Decl(unknownType2.ts, 1, 12))
|
||||
|
||||
type SomeResponse = 'yes' | 'no' | 'idk';
|
||||
>SomeResponse : Symbol(SomeResponse, Decl(unknownType2.ts, 1, 32))
|
||||
|
||||
let validate: (x: unknown) => SomeResponse = x => (x === 'yes' || x === 'no') ? x : 'idk'; // No error
|
||||
>validate : Symbol(validate, Decl(unknownType2.ts, 4, 3))
|
||||
>x : Symbol(x, Decl(unknownType2.ts, 4, 15))
|
||||
>SomeResponse : Symbol(SomeResponse, Decl(unknownType2.ts, 1, 32))
|
||||
>x : Symbol(x, Decl(unknownType2.ts, 4, 44))
|
||||
>x : Symbol(x, Decl(unknownType2.ts, 4, 44))
|
||||
>x : Symbol(x, Decl(unknownType2.ts, 4, 44))
|
||||
>x : Symbol(x, Decl(unknownType2.ts, 4, 44))
|
||||
|
||||
const u: unknown = undefined;
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
declare const symb: unique symbol;
|
||||
>symb : Symbol(symb, Decl(unknownType2.ts, 8, 13))
|
||||
|
||||
if (u === 5) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
|
||||
const y = u.toString(10);
|
||||
>y : Symbol(y, Decl(unknownType2.ts, 11, 9))
|
||||
>u.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
|
||||
if (u === true || u === false) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
|
||||
const someBool: boolean = u;
|
||||
>someBool : Symbol(someBool, Decl(unknownType2.ts, 15, 9))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if (u === undefined) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
const undef: undefined = u;
|
||||
>undef : Symbol(undef, Decl(unknownType2.ts, 19, 9))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if (u === null) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
|
||||
const someNull: null = u;
|
||||
>someNull : Symbol(someNull, Decl(unknownType2.ts, 23, 9))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if(u === symb) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
>symb : Symbol(symb, Decl(unknownType2.ts, 8, 13))
|
||||
|
||||
const symbolAlias: typeof symb = u;
|
||||
>symbolAlias : Symbol(symbolAlias, Decl(unknownType2.ts, 27, 9))
|
||||
>symb : Symbol(symb, Decl(unknownType2.ts, 8, 13))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if (!(u === 42)) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
|
||||
u // u should still be `unknown` here
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if (u !== 42) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
|
||||
type A = isTrue<isUnknown<typeof u>>
|
||||
>A : Symbol(A, Decl(unknownType2.ts, 34, 15))
|
||||
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
|
||||
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if (u == 42) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
|
||||
type B = isTrue<isUnknown<typeof u>>
|
||||
>B : Symbol(B, Decl(unknownType2.ts, 38, 14))
|
||||
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
|
||||
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if (u == true) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
|
||||
type C = isTrue<isUnknown<typeof u>>
|
||||
>C : Symbol(C, Decl(unknownType2.ts, 42, 16))
|
||||
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
|
||||
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
||||
if (u == Object) {
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
type D = isTrue<isUnknown<typeof u>>
|
||||
>D : Symbol(D, Decl(unknownType2.ts, 46, 18))
|
||||
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
|
||||
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
|
||||
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
|
||||
}
|
||||
|
148
tests/baselines/reference/unknownType2.types
Normal file
148
tests/baselines/reference/unknownType2.types
Normal file
|
@ -0,0 +1,148 @@
|
|||
=== tests/cases/conformance/types/unknown/unknownType2.ts ===
|
||||
type isUnknown<T> = unknown extends T ? true : false;
|
||||
>isUnknown : isUnknown<T>
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
type isTrue<T extends true> = T;
|
||||
>isTrue : T
|
||||
>true : true
|
||||
|
||||
type SomeResponse = 'yes' | 'no' | 'idk';
|
||||
>SomeResponse : SomeResponse
|
||||
|
||||
let validate: (x: unknown) => SomeResponse = x => (x === 'yes' || x === 'no') ? x : 'idk'; // No error
|
||||
>validate : (x: unknown) => SomeResponse
|
||||
>x : unknown
|
||||
>x => (x === 'yes' || x === 'no') ? x : 'idk' : (x: unknown) => "yes" | "no" | "idk"
|
||||
>x : unknown
|
||||
>(x === 'yes' || x === 'no') ? x : 'idk' : SomeResponse
|
||||
>(x === 'yes' || x === 'no') : boolean
|
||||
>x === 'yes' || x === 'no' : boolean
|
||||
>x === 'yes' : boolean
|
||||
>x : unknown
|
||||
>'yes' : "yes"
|
||||
>x === 'no' : boolean
|
||||
>x : unknown
|
||||
>'no' : "no"
|
||||
>x : "yes" | "no"
|
||||
>'idk' : "idk"
|
||||
|
||||
const u: unknown = undefined;
|
||||
>u : unknown
|
||||
>undefined : undefined
|
||||
|
||||
declare const symb: unique symbol;
|
||||
>symb : unique symbol
|
||||
|
||||
if (u === 5) {
|
||||
>u === 5 : boolean
|
||||
>u : unknown
|
||||
>5 : 5
|
||||
|
||||
const y = u.toString(10);
|
||||
>y : string
|
||||
>u.toString(10) : string
|
||||
>u.toString : (radix?: number | undefined) => string
|
||||
>u : 5
|
||||
>toString : (radix?: number | undefined) => string
|
||||
>10 : 10
|
||||
}
|
||||
|
||||
if (u === true || u === false) {
|
||||
>u === true || u === false : boolean
|
||||
>u === true : boolean
|
||||
>u : unknown
|
||||
>true : true
|
||||
>u === false : boolean
|
||||
>u : unknown
|
||||
>false : false
|
||||
|
||||
const someBool: boolean = u;
|
||||
>someBool : boolean
|
||||
>u : boolean
|
||||
}
|
||||
|
||||
if (u === undefined) {
|
||||
>u === undefined : boolean
|
||||
>u : unknown
|
||||
>undefined : undefined
|
||||
|
||||
const undef: undefined = u;
|
||||
>undef : undefined
|
||||
>u : undefined
|
||||
}
|
||||
|
||||
if (u === null) {
|
||||
>u === null : boolean
|
||||
>u : unknown
|
||||
>null : null
|
||||
|
||||
const someNull: null = u;
|
||||
>someNull : null
|
||||
>null : null
|
||||
>u : null
|
||||
}
|
||||
|
||||
if(u === symb) {
|
||||
>u === symb : boolean
|
||||
>u : unknown
|
||||
>symb : unique symbol
|
||||
|
||||
const symbolAlias: typeof symb = u;
|
||||
>symbolAlias : unique symbol
|
||||
>symb : unique symbol
|
||||
>u : unique symbol
|
||||
}
|
||||
|
||||
if (!(u === 42)) {
|
||||
>!(u === 42) : boolean
|
||||
>(u === 42) : boolean
|
||||
>u === 42 : boolean
|
||||
>u : unknown
|
||||
>42 : 42
|
||||
|
||||
u // u should still be `unknown` here
|
||||
>u : unknown
|
||||
}
|
||||
|
||||
if (u !== 42) {
|
||||
>u !== 42 : boolean
|
||||
>u : unknown
|
||||
>42 : 42
|
||||
|
||||
type A = isTrue<isUnknown<typeof u>>
|
||||
>A : true
|
||||
>u : unknown
|
||||
}
|
||||
|
||||
if (u == 42) {
|
||||
>u == 42 : boolean
|
||||
>u : unknown
|
||||
>42 : 42
|
||||
|
||||
type B = isTrue<isUnknown<typeof u>>
|
||||
>B : true
|
||||
>u : unknown
|
||||
}
|
||||
|
||||
if (u == true) {
|
||||
>u == true : boolean
|
||||
>u : unknown
|
||||
>true : true
|
||||
|
||||
type C = isTrue<isUnknown<typeof u>>
|
||||
>C : true
|
||||
>u : unknown
|
||||
}
|
||||
|
||||
if (u == Object) {
|
||||
>u == Object : boolean
|
||||
>u : unknown
|
||||
>Object : ObjectConstructor
|
||||
|
||||
type D = isTrue<isUnknown<typeof u>>
|
||||
>D : true
|
||||
>u : unknown
|
||||
}
|
||||
|
51
tests/cases/conformance/types/unknown/unknownType2.ts
Normal file
51
tests/cases/conformance/types/unknown/unknownType2.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
// @strict: true
|
||||
|
||||
type isUnknown<T> = unknown extends T ? true : false;
|
||||
type isTrue<T extends true> = T;
|
||||
|
||||
type SomeResponse = 'yes' | 'no' | 'idk';
|
||||
let validate: (x: unknown) => SomeResponse = x => (x === 'yes' || x === 'no') ? x : 'idk'; // No error
|
||||
|
||||
const u: unknown = undefined;
|
||||
|
||||
declare const symb: unique symbol;
|
||||
|
||||
if (u === 5) {
|
||||
const y = u.toString(10);
|
||||
}
|
||||
|
||||
if (u === true || u === false) {
|
||||
const someBool: boolean = u;
|
||||
}
|
||||
|
||||
if (u === undefined) {
|
||||
const undef: undefined = u;
|
||||
}
|
||||
|
||||
if (u === null) {
|
||||
const someNull: null = u;
|
||||
}
|
||||
|
||||
if(u === symb) {
|
||||
const symbolAlias: typeof symb = u;
|
||||
}
|
||||
|
||||
if (!(u === 42)) {
|
||||
u // u should still be `unknown` here
|
||||
}
|
||||
|
||||
if (u !== 42) {
|
||||
type A = isTrue<isUnknown<typeof u>>
|
||||
}
|
||||
|
||||
if (u == 42) {
|
||||
type B = isTrue<isUnknown<typeof u>>
|
||||
}
|
||||
|
||||
if (u == true) {
|
||||
type C = isTrue<isUnknown<typeof u>>
|
||||
}
|
||||
|
||||
if (u == Object) {
|
||||
type D = isTrue<isUnknown<typeof u>>
|
||||
}
|
Loading…
Reference in a new issue