From 90570dfe09a03691af9778634b4da74f22ad23cf Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 4 May 2020 17:12:58 -0700 Subject: [PATCH] Cherry-pick PR #38278 into release-3.9 (#38330) Component commits: d905cede25 Add missing getApparentType call c635e43ccc Add regression tests Co-authored-by: Anders Hejlsberg --- src/compiler/checker.ts | 2 +- .../reference/unionWithIndexSignature.js | 47 ++++++++++++ .../reference/unionWithIndexSignature.symbols | 72 +++++++++++++++++++ .../reference/unionWithIndexSignature.types | 62 ++++++++++++++++ .../cases/compiler/unionWithIndexSignature.ts | 28 ++++++++ 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/unionWithIndexSignature.js create mode 100644 tests/baselines/reference/unionWithIndexSignature.symbols create mode 100644 tests/baselines/reference/unionWithIndexSignature.types create mode 100644 tests/cases/compiler/unionWithIndexSignature.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ab655b128272c..7bc999936e81c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9647,7 +9647,7 @@ namespace ts { const indexTypes: Type[] = []; let isAnyReadonly = false; for (const type of types) { - const indexInfo = getIndexInfoOfType(type, kind); + const indexInfo = getIndexInfoOfType(getApparentType(type), kind); if (!indexInfo) { return undefined; } diff --git a/tests/baselines/reference/unionWithIndexSignature.js b/tests/baselines/reference/unionWithIndexSignature.js new file mode 100644 index 0000000000000..31e0ccb88d837 --- /dev/null +++ b/tests/baselines/reference/unionWithIndexSignature.js @@ -0,0 +1,47 @@ +//// [unionWithIndexSignature.ts] +interface NumList { + kind: 'n'; + [x: number]: number; +} +interface StrList { + kind: 's'; + [x: number]: string; +} + +export function foo(arr: T & (NumList | StrList)) { + let zz = arr[1]; // Error +} + +// Repro from #38102 + +export type TypedArray = Int32Array | Uint8Array; + +export function isTypedArray(a: {}): a is Int32Array | Uint8Array { + return a instanceof Int32Array || a instanceof Uint8Array; +} + +export function flatten(arr: T) { + if (isTypedArray(arr)) { + arr[1]; + } +} + + +//// [unionWithIndexSignature.js] +"use strict"; +exports.__esModule = true; +exports.flatten = exports.isTypedArray = exports.foo = void 0; +function foo(arr) { + var zz = arr[1]; // Error +} +exports.foo = foo; +function isTypedArray(a) { + return a instanceof Int32Array || a instanceof Uint8Array; +} +exports.isTypedArray = isTypedArray; +function flatten(arr) { + if (isTypedArray(arr)) { + arr[1]; + } +} +exports.flatten = flatten; diff --git a/tests/baselines/reference/unionWithIndexSignature.symbols b/tests/baselines/reference/unionWithIndexSignature.symbols new file mode 100644 index 0000000000000..5f78136b361a6 --- /dev/null +++ b/tests/baselines/reference/unionWithIndexSignature.symbols @@ -0,0 +1,72 @@ +=== tests/cases/compiler/unionWithIndexSignature.ts === +interface NumList { +>NumList : Symbol(NumList, Decl(unionWithIndexSignature.ts, 0, 0)) + + kind: 'n'; +>kind : Symbol(NumList.kind, Decl(unionWithIndexSignature.ts, 0, 19)) + + [x: number]: number; +>x : Symbol(x, Decl(unionWithIndexSignature.ts, 2, 3)) +} +interface StrList { +>StrList : Symbol(StrList, Decl(unionWithIndexSignature.ts, 3, 1)) + + kind: 's'; +>kind : Symbol(StrList.kind, Decl(unionWithIndexSignature.ts, 4, 19)) + + [x: number]: string; +>x : Symbol(x, Decl(unionWithIndexSignature.ts, 6, 3)) +} + +export function foo(arr: T & (NumList | StrList)) { +>foo : Symbol(foo, Decl(unionWithIndexSignature.ts, 7, 1)) +>T : Symbol(T, Decl(unionWithIndexSignature.ts, 9, 20)) +>NumList : Symbol(NumList, Decl(unionWithIndexSignature.ts, 0, 0)) +>StrList : Symbol(StrList, Decl(unionWithIndexSignature.ts, 3, 1)) +>arr : Symbol(arr, Decl(unionWithIndexSignature.ts, 9, 49)) +>T : Symbol(T, Decl(unionWithIndexSignature.ts, 9, 20)) +>NumList : Symbol(NumList, Decl(unionWithIndexSignature.ts, 0, 0)) +>StrList : Symbol(StrList, Decl(unionWithIndexSignature.ts, 3, 1)) + + let zz = arr[1]; // Error +>zz : Symbol(zz, Decl(unionWithIndexSignature.ts, 10, 5)) +>arr : Symbol(arr, Decl(unionWithIndexSignature.ts, 9, 49)) +} + +// Repro from #38102 + +export type TypedArray = Int32Array | Uint8Array; +>TypedArray : Symbol(TypedArray, Decl(unionWithIndexSignature.ts, 11, 1)) +>Int32Array : Symbol(Int32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Uint8Array : Symbol(Uint8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +export function isTypedArray(a: {}): a is Int32Array | Uint8Array { +>isTypedArray : Symbol(isTypedArray, Decl(unionWithIndexSignature.ts, 15, 49)) +>a : Symbol(a, Decl(unionWithIndexSignature.ts, 17, 29)) +>a : Symbol(a, Decl(unionWithIndexSignature.ts, 17, 29)) +>Int32Array : Symbol(Int32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Uint8Array : Symbol(Uint8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + return a instanceof Int32Array || a instanceof Uint8Array; +>a : Symbol(a, Decl(unionWithIndexSignature.ts, 17, 29)) +>Int32Array : Symbol(Int32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(unionWithIndexSignature.ts, 17, 29)) +>Uint8Array : Symbol(Uint8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +} + +export function flatten(arr: T) { +>flatten : Symbol(flatten, Decl(unionWithIndexSignature.ts, 19, 1)) +>T : Symbol(T, Decl(unionWithIndexSignature.ts, 21, 24)) +>TypedArray : Symbol(TypedArray, Decl(unionWithIndexSignature.ts, 11, 1)) +>arr : Symbol(arr, Decl(unionWithIndexSignature.ts, 21, 53)) +>T : Symbol(T, Decl(unionWithIndexSignature.ts, 21, 24)) + + if (isTypedArray(arr)) { +>isTypedArray : Symbol(isTypedArray, Decl(unionWithIndexSignature.ts, 15, 49)) +>arr : Symbol(arr, Decl(unionWithIndexSignature.ts, 21, 53)) + + arr[1]; +>arr : Symbol(arr, Decl(unionWithIndexSignature.ts, 21, 53)) + } +} + diff --git a/tests/baselines/reference/unionWithIndexSignature.types b/tests/baselines/reference/unionWithIndexSignature.types new file mode 100644 index 0000000000000..d80e8d01ca3c4 --- /dev/null +++ b/tests/baselines/reference/unionWithIndexSignature.types @@ -0,0 +1,62 @@ +=== tests/cases/compiler/unionWithIndexSignature.ts === +interface NumList { + kind: 'n'; +>kind : "n" + + [x: number]: number; +>x : number +} +interface StrList { + kind: 's'; +>kind : "s" + + [x: number]: string; +>x : number +} + +export function foo(arr: T & (NumList | StrList)) { +>foo : (arr: T & (NumList | StrList)) => void +>arr : (T & NumList) | (T & StrList) + + let zz = arr[1]; // Error +>zz : string | number +>arr[1] : string | number +>arr : (T & NumList) | (T & StrList) +>1 : 1 +} + +// Repro from #38102 + +export type TypedArray = Int32Array | Uint8Array; +>TypedArray : Int32Array | Uint8Array + +export function isTypedArray(a: {}): a is Int32Array | Uint8Array { +>isTypedArray : (a: {}) => a is Int32Array | Uint8Array +>a : {} + + return a instanceof Int32Array || a instanceof Uint8Array; +>a instanceof Int32Array || a instanceof Uint8Array : boolean +>a instanceof Int32Array : boolean +>a : {} +>Int32Array : Int32ArrayConstructor +>a instanceof Uint8Array : boolean +>a : {} +>Uint8Array : Uint8ArrayConstructor +} + +export function flatten(arr: T) { +>flatten : (arr: T) => void +>arr : T + + if (isTypedArray(arr)) { +>isTypedArray(arr) : boolean +>isTypedArray : (a: {}) => a is Int32Array | Uint8Array +>arr : T + + arr[1]; +>arr[1] : number +>arr : (T & Int32Array) | (T & Uint8Array) +>1 : 1 + } +} + diff --git a/tests/cases/compiler/unionWithIndexSignature.ts b/tests/cases/compiler/unionWithIndexSignature.ts new file mode 100644 index 0000000000000..14b20f3d57612 --- /dev/null +++ b/tests/cases/compiler/unionWithIndexSignature.ts @@ -0,0 +1,28 @@ +// @strict: true + +interface NumList { + kind: 'n'; + [x: number]: number; +} +interface StrList { + kind: 's'; + [x: number]: string; +} + +export function foo(arr: T & (NumList | StrList)) { + let zz = arr[1]; // Error +} + +// Repro from #38102 + +export type TypedArray = Int32Array | Uint8Array; + +export function isTypedArray(a: {}): a is Int32Array | Uint8Array { + return a instanceof Int32Array || a instanceof Uint8Array; +} + +export function flatten(arr: T) { + if (isTypedArray(arr)) { + arr[1]; + } +}