mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Exclude special index signature rule from strict subtype relation (#53388)
Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
parent
7009c76d00
commit
25550bd3d6
@ -22485,7 +22485,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const targetHasStringIndex = some(indexInfos, info => info.keyType === stringType);
|
||||
let result = Ternary.True;
|
||||
for (const targetInfo of indexInfos) {
|
||||
const related = !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True :
|
||||
const related = relation !== strictSubtypeRelation && !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True :
|
||||
isGenericMappedType(source) && targetHasStringIndex ? isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, RecursionFlags.Both, reportErrors) :
|
||||
typeRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState);
|
||||
if (!related) {
|
||||
|
||||
155
tests/baselines/reference/narrowingMutualSubtypes.errors.txt
Normal file
155
tests/baselines/reference/narrowingMutualSubtypes.errors.txt
Normal file
@ -0,0 +1,155 @@
|
||||
tests/cases/compiler/narrowingMutualSubtypes.ts(117,17): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record<string, any>'.
|
||||
No index signature with a parameter of type 'string' was found on type 'any[] | Record<string, any>'.
|
||||
tests/cases/compiler/narrowingMutualSubtypes.ts(118,29): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record<string, any>'.
|
||||
No index signature with a parameter of type 'string' was found on type 'any[] | Record<string, any>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/narrowingMutualSubtypes.ts (2 errors) ====
|
||||
// Check that `any` is a strict supertype of `unknown`
|
||||
|
||||
declare const ru1: { [x: string]: unknown };
|
||||
declare const ra1: { [x: string]: any };
|
||||
|
||||
const a1a = [ru1, ra1]; // { [x: string]: any }[]
|
||||
const a1b = [ra1, ru1]; // { [x: string]: any }[]
|
||||
|
||||
declare const ra2: { [x: string]: any };
|
||||
declare const ru2: { [x: string]: unknown };
|
||||
|
||||
const a2a = [ru2, ra2]; // { [x: string]: any }[]
|
||||
const a2b = [ra2, ru2]; // { [x: string]: any }[]
|
||||
|
||||
// Check that `{}` is strict supertype of any non-empty object
|
||||
|
||||
const c3 = {};
|
||||
declare const r3: { [x: string]: unknown }
|
||||
|
||||
const a3a = [c3, r3]; // {}[]
|
||||
const a3b = [r3, c3]; // {}[]
|
||||
|
||||
declare const r4: { [x: string]: unknown }
|
||||
const c4 = {};
|
||||
|
||||
const a4a = [c4, r4]; // {}[]
|
||||
const a4b = [r4, c4]; // {}[]
|
||||
|
||||
// Check that {} is a strict supertype of Record<string, unknown>
|
||||
|
||||
declare function isObject1(value: unknown): value is Record<string, unknown>;
|
||||
|
||||
function gg1(x: {}) {
|
||||
if (isObject1(x)) {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
x; // {}
|
||||
}
|
||||
|
||||
declare function isObject2(value: unknown): value is {};
|
||||
|
||||
function gg2(x: Record<string, unknown>) {
|
||||
if (isObject2(x)) {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
|
||||
// Check that {} is a strict supertype of Record<string, any>
|
||||
|
||||
declare function isObject3(value: unknown): value is Record<string, any>;
|
||||
|
||||
function gg3(x: {}) {
|
||||
if (isObject3(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
x; // {}
|
||||
}
|
||||
|
||||
declare function isObject4(value: unknown): value is {};
|
||||
|
||||
function gg4(x: Record<string, any>) {
|
||||
if (isObject4(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, any>
|
||||
}
|
||||
|
||||
// Repro from #50916
|
||||
|
||||
type Identity<T> = {[K in keyof T]: T[K]};
|
||||
|
||||
type Self<T> = T extends unknown ? Identity<T> : never;
|
||||
|
||||
function is<T>(value: T): value is Self<T> {
|
||||
return true;
|
||||
}
|
||||
|
||||
type Union = {a: number} | {b: number} | {c: number};
|
||||
|
||||
function example(x: Union) {
|
||||
if (is(x)) {}
|
||||
if (is(x)) {}
|
||||
if (is(x)) {}
|
||||
if (is(x)) {}
|
||||
if (is(x)) {}
|
||||
if (is(x)) {}
|
||||
if (is(x)) {}
|
||||
if (is(x)) {}
|
||||
x; // Union
|
||||
}
|
||||
|
||||
function checksArrayOrObject1(obj: Record<string, any> | Record<string, any>[]) {
|
||||
// "accidentally" guards the first branch on the length
|
||||
if (Array.isArray(obj) && obj.length) {
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
~~~~~~~~
|
||||
!!! error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record<string, any>'.
|
||||
!!! error TS7053: No index signature with a parameter of type 'string' was found on type 'any[] | Record<string, any>'.
|
||||
console.log(obj[key])
|
||||
~~~~~~~~
|
||||
!!! error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'any[] | Record<string, any>'.
|
||||
!!! error TS7053: No index signature with a parameter of type 'string' was found on type 'any[] | Record<string, any>'.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checksArrayOrObject2(obj: Record<string, any> | Record<string, any>[]) {
|
||||
if (Array.isArray(obj)) {
|
||||
// obj should only be an array type here
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,11 +27,11 @@ const c4 = {};
|
||||
const a4a = [c4, r4]; // {}[]
|
||||
const a4b = [r4, c4]; // {}[]
|
||||
|
||||
// Check that narrowing preserves original type in false branch for non-identical mutual subtypes
|
||||
// Check that {} is a strict supertype of Record<string, unknown>
|
||||
|
||||
declare function isObject1(value: unknown): value is Record<string, unknown>;
|
||||
|
||||
function gg(x: {}) {
|
||||
function gg1(x: {}) {
|
||||
if (isObject1(x)) {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
@ -45,14 +45,40 @@ declare function isObject2(value: unknown): value is {};
|
||||
|
||||
function gg2(x: Record<string, unknown>) {
|
||||
if (isObject2(x)) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
|
||||
// Check that {} is a strict supertype of Record<string, any>
|
||||
|
||||
declare function isObject3(value: unknown): value is Record<string, any>;
|
||||
|
||||
function gg3(x: {}) {
|
||||
if (isObject3(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
x; // {}
|
||||
}
|
||||
|
||||
declare function isObject4(value: unknown): value is {};
|
||||
|
||||
function gg4(x: Record<string, any>) {
|
||||
if (isObject4(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, any>
|
||||
}
|
||||
|
||||
// Repro from #50916
|
||||
|
||||
type Identity<T> = {[K in keyof T]: T[K]};
|
||||
@ -76,6 +102,44 @@ function example(x: Union) {
|
||||
if (is(x)) {}
|
||||
x; // Union
|
||||
}
|
||||
|
||||
function checksArrayOrObject1(obj: Record<string, any> | Record<string, any>[]) {
|
||||
// "accidentally" guards the first branch on the length
|
||||
if (Array.isArray(obj) && obj.length) {
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checksArrayOrObject2(obj: Record<string, any> | Record<string, any>[]) {
|
||||
if (Array.isArray(obj)) {
|
||||
// obj should only be an array type here
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [narrowingMutualSubtypes.js]
|
||||
@ -92,7 +156,7 @@ var a3b = [r3, c3]; // {}[]
|
||||
var c4 = {};
|
||||
var a4a = [c4, r4]; // {}[]
|
||||
var a4b = [r4, c4]; // {}[]
|
||||
function gg(x) {
|
||||
function gg1(x) {
|
||||
if (isObject1(x)) {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
@ -103,13 +167,31 @@ function gg(x) {
|
||||
}
|
||||
function gg2(x) {
|
||||
if (isObject2(x)) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
function gg3(x) {
|
||||
if (isObject3(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
x; // {}
|
||||
}
|
||||
function gg4(x) {
|
||||
if (isObject4(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, any>
|
||||
}
|
||||
function is(value) {
|
||||
return true;
|
||||
}
|
||||
@ -124,3 +206,39 @@ function example(x) {
|
||||
if (is(x)) { }
|
||||
x; // Union
|
||||
}
|
||||
function checksArrayOrObject1(obj) {
|
||||
// "accidentally" guards the first branch on the length
|
||||
if (Array.isArray(obj) && obj.length) {
|
||||
for (var key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (var key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function checksArrayOrObject2(obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
// obj should only be an array type here
|
||||
for (var key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (var key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ const a4b = [r4, c4]; // {}[]
|
||||
>r4 : Symbol(r4, Decl(narrowingMutualSubtypes.ts, 22, 13))
|
||||
>c4 : Symbol(c4, Decl(narrowingMutualSubtypes.ts, 23, 5))
|
||||
|
||||
// Check that narrowing preserves original type in false branch for non-identical mutual subtypes
|
||||
// Check that {} is a strict supertype of Record<string, unknown>
|
||||
|
||||
declare function isObject1(value: unknown): value is Record<string, unknown>;
|
||||
>isObject1 : Symbol(isObject1, Decl(narrowingMutualSubtypes.ts, 26, 21))
|
||||
@ -81,23 +81,23 @@ declare function isObject1(value: unknown): value is Record<string, unknown>;
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 30, 27))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
function gg(x: {}) {
|
||||
>gg : Symbol(gg, Decl(narrowingMutualSubtypes.ts, 30, 77))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 12))
|
||||
function gg1(x: {}) {
|
||||
>gg1 : Symbol(gg1, Decl(narrowingMutualSubtypes.ts, 30, 77))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 13))
|
||||
|
||||
if (isObject1(x)) {
|
||||
>isObject1 : Symbol(isObject1, Decl(narrowingMutualSubtypes.ts, 26, 21))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 12))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 13))
|
||||
|
||||
x; // Record<string, unknown>
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 12))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 13))
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 12))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 13))
|
||||
}
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 12))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 32, 13))
|
||||
}
|
||||
|
||||
declare function isObject2(value: unknown): value is {};
|
||||
@ -114,90 +114,251 @@ function gg2(x: Record<string, unknown>) {
|
||||
>isObject2 : Symbol(isObject2, Decl(narrowingMutualSubtypes.ts, 40, 1))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 44, 13))
|
||||
|
||||
x; // {}
|
||||
x; // Record<string, unknown>
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 44, 13))
|
||||
}
|
||||
else {
|
||||
x; // Record<string, unknown>
|
||||
x; // never
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 44, 13))
|
||||
}
|
||||
x; // Record<string, unknown>
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 44, 13))
|
||||
}
|
||||
|
||||
// Check that {} is a strict supertype of Record<string, any>
|
||||
|
||||
declare function isObject3(value: unknown): value is Record<string, any>;
|
||||
>isObject3 : Symbol(isObject3, Decl(narrowingMutualSubtypes.ts, 52, 1))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 56, 27))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 56, 27))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
function gg3(x: {}) {
|
||||
>gg3 : Symbol(gg3, Decl(narrowingMutualSubtypes.ts, 56, 73))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 58, 13))
|
||||
|
||||
if (isObject3(x)) {
|
||||
>isObject3 : Symbol(isObject3, Decl(narrowingMutualSubtypes.ts, 52, 1))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 58, 13))
|
||||
|
||||
x; // Record<string, any>
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 58, 13))
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 58, 13))
|
||||
}
|
||||
x; // {}
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 58, 13))
|
||||
}
|
||||
|
||||
declare function isObject4(value: unknown): value is {};
|
||||
>isObject4 : Symbol(isObject4, Decl(narrowingMutualSubtypes.ts, 66, 1))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 68, 27))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 68, 27))
|
||||
|
||||
function gg4(x: Record<string, any>) {
|
||||
>gg4 : Symbol(gg4, Decl(narrowingMutualSubtypes.ts, 68, 56))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 70, 13))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
if (isObject4(x)) {
|
||||
>isObject4 : Symbol(isObject4, Decl(narrowingMutualSubtypes.ts, 66, 1))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 70, 13))
|
||||
|
||||
x; // Record<string, any>
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 70, 13))
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 70, 13))
|
||||
}
|
||||
x; // Record<string, any>
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 70, 13))
|
||||
}
|
||||
|
||||
// Repro from #50916
|
||||
|
||||
type Identity<T> = {[K in keyof T]: T[K]};
|
||||
>Identity : Symbol(Identity, Decl(narrowingMutualSubtypes.ts, 52, 1))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 56, 14))
|
||||
>K : Symbol(K, Decl(narrowingMutualSubtypes.ts, 56, 21))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 56, 14))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 56, 14))
|
||||
>K : Symbol(K, Decl(narrowingMutualSubtypes.ts, 56, 21))
|
||||
>Identity : Symbol(Identity, Decl(narrowingMutualSubtypes.ts, 78, 1))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 82, 14))
|
||||
>K : Symbol(K, Decl(narrowingMutualSubtypes.ts, 82, 21))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 82, 14))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 82, 14))
|
||||
>K : Symbol(K, Decl(narrowingMutualSubtypes.ts, 82, 21))
|
||||
|
||||
type Self<T> = T extends unknown ? Identity<T> : never;
|
||||
>Self : Symbol(Self, Decl(narrowingMutualSubtypes.ts, 56, 42))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 58, 10))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 58, 10))
|
||||
>Identity : Symbol(Identity, Decl(narrowingMutualSubtypes.ts, 52, 1))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 58, 10))
|
||||
>Self : Symbol(Self, Decl(narrowingMutualSubtypes.ts, 82, 42))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 84, 10))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 84, 10))
|
||||
>Identity : Symbol(Identity, Decl(narrowingMutualSubtypes.ts, 78, 1))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 84, 10))
|
||||
|
||||
function is<T>(value: T): value is Self<T> {
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 60, 12))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 60, 15))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 60, 12))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 60, 15))
|
||||
>Self : Symbol(Self, Decl(narrowingMutualSubtypes.ts, 56, 42))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 60, 12))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 86, 12))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 86, 15))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 86, 12))
|
||||
>value : Symbol(value, Decl(narrowingMutualSubtypes.ts, 86, 15))
|
||||
>Self : Symbol(Self, Decl(narrowingMutualSubtypes.ts, 82, 42))
|
||||
>T : Symbol(T, Decl(narrowingMutualSubtypes.ts, 86, 12))
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
type Union = {a: number} | {b: number} | {c: number};
|
||||
>Union : Symbol(Union, Decl(narrowingMutualSubtypes.ts, 62, 1))
|
||||
>a : Symbol(a, Decl(narrowingMutualSubtypes.ts, 64, 15))
|
||||
>b : Symbol(b, Decl(narrowingMutualSubtypes.ts, 64, 29))
|
||||
>c : Symbol(c, Decl(narrowingMutualSubtypes.ts, 64, 43))
|
||||
>Union : Symbol(Union, Decl(narrowingMutualSubtypes.ts, 88, 1))
|
||||
>a : Symbol(a, Decl(narrowingMutualSubtypes.ts, 90, 15))
|
||||
>b : Symbol(b, Decl(narrowingMutualSubtypes.ts, 90, 29))
|
||||
>c : Symbol(c, Decl(narrowingMutualSubtypes.ts, 90, 43))
|
||||
|
||||
function example(x: Union) {
|
||||
>example : Symbol(example, Decl(narrowingMutualSubtypes.ts, 64, 54))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>Union : Symbol(Union, Decl(narrowingMutualSubtypes.ts, 62, 1))
|
||||
>example : Symbol(example, Decl(narrowingMutualSubtypes.ts, 90, 54))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
>Union : Symbol(Union, Decl(narrowingMutualSubtypes.ts, 88, 1))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
if (is(x)) {}
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 58, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>is : Symbol(is, Decl(narrowingMutualSubtypes.ts, 84, 55))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
|
||||
x; // Union
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 66, 17))
|
||||
>x : Symbol(x, Decl(narrowingMutualSubtypes.ts, 92, 17))
|
||||
}
|
||||
|
||||
function checksArrayOrObject1(obj: Record<string, any> | Record<string, any>[]) {
|
||||
>checksArrayOrObject1 : Symbol(checksArrayOrObject1, Decl(narrowingMutualSubtypes.ts, 102, 1))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
// "accidentally" guards the first branch on the length
|
||||
if (Array.isArray(obj) && obj.length) {
|
||||
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
>obj.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
for (let key in obj) {
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 107, 16))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 107, 16))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 107, 16))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 115, 16))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 115, 16))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 104, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 115, 16))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checksArrayOrObject2(obj: Record<string, any> | Record<string, any>[]) {
|
||||
>checksArrayOrObject2 : Symbol(checksArrayOrObject2, Decl(narrowingMutualSubtypes.ts, 121, 1))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
|
||||
// obj should only be an array type here
|
||||
for (let key in obj) {
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 126, 16))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 126, 16))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 126, 16))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 134, 16))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 134, 16))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>obj : Symbol(obj, Decl(narrowingMutualSubtypes.ts, 123, 30))
|
||||
>key : Symbol(key, Decl(narrowingMutualSubtypes.ts, 134, 16))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -83,14 +83,14 @@ const a4b = [r4, c4]; // {}[]
|
||||
>r4 : { [x: string]: unknown; }
|
||||
>c4 : {}
|
||||
|
||||
// Check that narrowing preserves original type in false branch for non-identical mutual subtypes
|
||||
// Check that {} is a strict supertype of Record<string, unknown>
|
||||
|
||||
declare function isObject1(value: unknown): value is Record<string, unknown>;
|
||||
>isObject1 : (value: unknown) => value is Record<string, unknown>
|
||||
>value : unknown
|
||||
|
||||
function gg(x: {}) {
|
||||
>gg : (x: {}) => void
|
||||
function gg1(x: {}) {
|
||||
>gg1 : (x: {}) => void
|
||||
>x : {}
|
||||
|
||||
if (isObject1(x)) {
|
||||
@ -122,17 +122,67 @@ function gg2(x: Record<string, unknown>) {
|
||||
>isObject2 : (value: unknown) => value is {}
|
||||
>x : Record<string, unknown>
|
||||
|
||||
x; // {}
|
||||
x; // Record<string, unknown>
|
||||
>x : Record<string, unknown>
|
||||
}
|
||||
else {
|
||||
x; // Record<string, unknown>
|
||||
x; // never
|
||||
>x : never
|
||||
}
|
||||
x; // Record<string, unknown>
|
||||
>x : Record<string, unknown>
|
||||
}
|
||||
|
||||
// Check that {} is a strict supertype of Record<string, any>
|
||||
|
||||
declare function isObject3(value: unknown): value is Record<string, any>;
|
||||
>isObject3 : (value: unknown) => value is Record<string, any>
|
||||
>value : unknown
|
||||
|
||||
function gg3(x: {}) {
|
||||
>gg3 : (x: {}) => void
|
||||
>x : {}
|
||||
|
||||
if (isObject3(x)) {
|
||||
>isObject3(x) : boolean
|
||||
>isObject3 : (value: unknown) => value is Record<string, any>
|
||||
>x : {}
|
||||
|
||||
x; // Record<string, any>
|
||||
>x : Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
>x : {}
|
||||
}
|
||||
x; // {}
|
||||
>x : {}
|
||||
}
|
||||
|
||||
declare function isObject4(value: unknown): value is {};
|
||||
>isObject4 : (value: unknown) => value is {}
|
||||
>value : unknown
|
||||
|
||||
function gg4(x: Record<string, any>) {
|
||||
>gg4 : (x: Record<string, any>) => void
|
||||
>x : Record<string, any>
|
||||
|
||||
if (isObject4(x)) {
|
||||
>isObject4(x) : boolean
|
||||
>isObject4 : (value: unknown) => value is {}
|
||||
>x : Record<string, any>
|
||||
|
||||
x; // Record<string, any>
|
||||
>x : Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
>x : never
|
||||
}
|
||||
x; // Record<string, any>
|
||||
>x : Record<string, any>
|
||||
}
|
||||
|
||||
// Repro from #50916
|
||||
|
||||
type Identity<T> = {[K in keyof T]: T[K]};
|
||||
@ -203,3 +253,127 @@ function example(x: Union) {
|
||||
>x : Union
|
||||
}
|
||||
|
||||
function checksArrayOrObject1(obj: Record<string, any> | Record<string, any>[]) {
|
||||
>checksArrayOrObject1 : (obj: Record<string, any> | Record<string, any>[]) => void
|
||||
>obj : Record<string, any> | Record<string, any>[]
|
||||
|
||||
// "accidentally" guards the first branch on the length
|
||||
if (Array.isArray(obj) && obj.length) {
|
||||
>Array.isArray(obj) && obj.length : number | false
|
||||
>Array.isArray(obj) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>obj : Record<string, any> | Record<string, any>[]
|
||||
>obj.length : number
|
||||
>obj : any[] | Record<string, any>[]
|
||||
>length : number
|
||||
|
||||
for (let key in obj) {
|
||||
>key : string
|
||||
>obj : any[] | Record<string, any>[]
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj[key] !== undefined : boolean
|
||||
>obj[key] : any
|
||||
>obj : any[] | Record<string, any>[]
|
||||
>key : string
|
||||
>undefined : undefined
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log(obj[key]) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>obj[key] : any
|
||||
>obj : any[] | Record<string, any>[]
|
||||
>key : string
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
>key : string
|
||||
>obj : any[] | Record<string, any>
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj[key] !== undefined : boolean
|
||||
>obj[key] : any
|
||||
>obj : any[] | Record<string, any>
|
||||
>key : string
|
||||
>undefined : undefined
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log(obj[key]) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>obj[key] : any
|
||||
>obj : any[] | Record<string, any>
|
||||
>key : string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checksArrayOrObject2(obj: Record<string, any> | Record<string, any>[]) {
|
||||
>checksArrayOrObject2 : (obj: Record<string, any> | Record<string, any>[]) => void
|
||||
>obj : Record<string, any> | Record<string, any>[]
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
>Array.isArray(obj) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>obj : Record<string, any> | Record<string, any>[]
|
||||
|
||||
// obj should only be an array type here
|
||||
for (let key in obj) {
|
||||
>key : string
|
||||
>obj : any[] | Record<string, any>[]
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj[key] !== undefined : boolean
|
||||
>obj[key] : any
|
||||
>obj : any[] | Record<string, any>[]
|
||||
>key : string
|
||||
>undefined : undefined
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log(obj[key]) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>obj[key] : any
|
||||
>obj : any[] | Record<string, any>[]
|
||||
>key : string
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
>key : string
|
||||
>obj : Record<string, any>
|
||||
|
||||
if (obj[key] !== undefined) {
|
||||
>obj[key] !== undefined : boolean
|
||||
>obj[key] : any
|
||||
>obj : Record<string, any>
|
||||
>key : string
|
||||
>undefined : undefined
|
||||
|
||||
console.log(obj[key])
|
||||
>console.log(obj[key]) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>obj[key] : any
|
||||
>obj : Record<string, any>
|
||||
>key : string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -28,11 +28,11 @@ const c4 = {};
|
||||
const a4a = [c4, r4]; // {}[]
|
||||
const a4b = [r4, c4]; // {}[]
|
||||
|
||||
// Check that narrowing preserves original type in false branch for non-identical mutual subtypes
|
||||
// Check that {} is a strict supertype of Record<string, unknown>
|
||||
|
||||
declare function isObject1(value: unknown): value is Record<string, unknown>;
|
||||
|
||||
function gg(x: {}) {
|
||||
function gg1(x: {}) {
|
||||
if (isObject1(x)) {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
@ -46,14 +46,40 @@ declare function isObject2(value: unknown): value is {};
|
||||
|
||||
function gg2(x: Record<string, unknown>) {
|
||||
if (isObject2(x)) {
|
||||
x; // {}
|
||||
}
|
||||
else {
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, unknown>
|
||||
}
|
||||
|
||||
// Check that {} is a strict supertype of Record<string, any>
|
||||
|
||||
declare function isObject3(value: unknown): value is Record<string, any>;
|
||||
|
||||
function gg3(x: {}) {
|
||||
if (isObject3(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // {}
|
||||
}
|
||||
x; // {}
|
||||
}
|
||||
|
||||
declare function isObject4(value: unknown): value is {};
|
||||
|
||||
function gg4(x: Record<string, any>) {
|
||||
if (isObject4(x)) {
|
||||
x; // Record<string, any>
|
||||
}
|
||||
else {
|
||||
x; // never
|
||||
}
|
||||
x; // Record<string, any>
|
||||
}
|
||||
|
||||
// Repro from #50916
|
||||
|
||||
type Identity<T> = {[K in keyof T]: T[K]};
|
||||
@ -77,3 +103,41 @@ function example(x: Union) {
|
||||
if (is(x)) {}
|
||||
x; // Union
|
||||
}
|
||||
|
||||
function checksArrayOrObject1(obj: Record<string, any> | Record<string, any>[]) {
|
||||
// "accidentally" guards the first branch on the length
|
||||
if (Array.isArray(obj) && obj.length) {
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checksArrayOrObject2(obj: Record<string, any> | Record<string, any>[]) {
|
||||
if (Array.isArray(obj)) {
|
||||
// obj should only be an array type here
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 'obj' should probably not include an array type here.
|
||||
for (let key in obj) {
|
||||
if (obj[key] !== undefined) {
|
||||
console.log(obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user