From ec48ce89da1c539b529bf23221319042fb18186c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 20 Jul 2023 16:55:35 +0200 Subject: [PATCH] Fixed expando functions with nullish properties (#54728) --- src/compiler/checker.ts | 2 +- .../expandoFunctionNullishProperty.js | 75 ++++++++++++++++++ .../expandoFunctionNullishProperty.symbols | 78 +++++++++++++++++++ .../expandoFunctionNullishProperty.types | 72 +++++++++++++++++ .../expandoFunctionNullishProperty.ts | 38 +++++++++ 5 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/expandoFunctionNullishProperty.js create mode 100644 tests/baselines/reference/expandoFunctionNullishProperty.symbols create mode 100644 tests/baselines/reference/expandoFunctionNullishProperty.types create mode 100644 tests/cases/compiler/expandoFunctionNullishProperty.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4bd721c6b13..71b5dcde9c0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10750,7 +10750,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const widened = getWidenedType(addOptionality(type, /*isProperty*/ false, definedInMethod && !definedInConstructor)); - if (symbol.valueDeclaration && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) { + if (symbol.valueDeclaration && isInJSFile(symbol.valueDeclaration) && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) { reportImplicitAny(symbol.valueDeclaration, anyType); return anyType; } diff --git a/tests/baselines/reference/expandoFunctionNullishProperty.js b/tests/baselines/reference/expandoFunctionNullishProperty.js new file mode 100644 index 00000000000..cd984003441 --- /dev/null +++ b/tests/baselines/reference/expandoFunctionNullishProperty.js @@ -0,0 +1,75 @@ +//// [tests/cases/compiler/expandoFunctionNullishProperty.ts] //// + +//// [expandoFunctionNullishProperty.ts] +// mentioned in https://github.com/microsoft/TypeScript/issues/54220 + +interface TestNull { + (): void; + readonly prop: null; +} + +export function testNull(): TestNull { + function inner() {} + inner.prop = null; + return inner; +} + +interface TestNull2 { + (): void; + prop: string | null; +} + +export function testNull2(): TestNull2 { + function inner() {} + inner.prop = null; + return inner; +} + +interface TestUndefined { + (): void; + readonly prop: undefined; +} + +export function testUndefined(): TestUndefined { + function inner() {} + inner.prop = undefined; + return inner; +} + + +//// [expandoFunctionNullishProperty.js] +// mentioned in https://github.com/microsoft/TypeScript/issues/54220 +export function testNull() { + function inner() { } + inner.prop = null; + return inner; +} +export function testNull2() { + function inner() { } + inner.prop = null; + return inner; +} +export function testUndefined() { + function inner() { } + inner.prop = undefined; + return inner; +} + + +//// [expandoFunctionNullishProperty.d.ts] +interface TestNull { + (): void; + readonly prop: null; +} +export declare function testNull(): TestNull; +interface TestNull2 { + (): void; + prop: string | null; +} +export declare function testNull2(): TestNull2; +interface TestUndefined { + (): void; + readonly prop: undefined; +} +export declare function testUndefined(): TestUndefined; +export {}; diff --git a/tests/baselines/reference/expandoFunctionNullishProperty.symbols b/tests/baselines/reference/expandoFunctionNullishProperty.symbols new file mode 100644 index 00000000000..f2314e49e08 --- /dev/null +++ b/tests/baselines/reference/expandoFunctionNullishProperty.symbols @@ -0,0 +1,78 @@ +//// [tests/cases/compiler/expandoFunctionNullishProperty.ts] //// + +=== expandoFunctionNullishProperty.ts === +// mentioned in https://github.com/microsoft/TypeScript/issues/54220 + +interface TestNull { +>TestNull : Symbol(TestNull, Decl(expandoFunctionNullishProperty.ts, 0, 0)) + + (): void; + readonly prop: null; +>prop : Symbol(TestNull.prop, Decl(expandoFunctionNullishProperty.ts, 3, 11)) +} + +export function testNull(): TestNull { +>testNull : Symbol(testNull, Decl(expandoFunctionNullishProperty.ts, 5, 1)) +>TestNull : Symbol(TestNull, Decl(expandoFunctionNullishProperty.ts, 0, 0)) + + function inner() {} +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 7, 38)) + + inner.prop = null; +>inner.prop : Symbol(inner.prop, Decl(expandoFunctionNullishProperty.ts, 8, 21)) +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 7, 38)) +>prop : Symbol(inner.prop, Decl(expandoFunctionNullishProperty.ts, 8, 21)) + + return inner; +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 7, 38)) +} + +interface TestNull2 { +>TestNull2 : Symbol(TestNull2, Decl(expandoFunctionNullishProperty.ts, 11, 1)) + + (): void; + prop: string | null; +>prop : Symbol(TestNull2.prop, Decl(expandoFunctionNullishProperty.ts, 14, 11)) +} + +export function testNull2(): TestNull2 { +>testNull2 : Symbol(testNull2, Decl(expandoFunctionNullishProperty.ts, 16, 1)) +>TestNull2 : Symbol(TestNull2, Decl(expandoFunctionNullishProperty.ts, 11, 1)) + + function inner() {} +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 18, 40)) + + inner.prop = null; +>inner.prop : Symbol(inner.prop, Decl(expandoFunctionNullishProperty.ts, 19, 21)) +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 18, 40)) +>prop : Symbol(inner.prop, Decl(expandoFunctionNullishProperty.ts, 19, 21)) + + return inner; +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 18, 40)) +} + +interface TestUndefined { +>TestUndefined : Symbol(TestUndefined, Decl(expandoFunctionNullishProperty.ts, 22, 1)) + + (): void; + readonly prop: undefined; +>prop : Symbol(TestUndefined.prop, Decl(expandoFunctionNullishProperty.ts, 25, 11)) +} + +export function testUndefined(): TestUndefined { +>testUndefined : Symbol(testUndefined, Decl(expandoFunctionNullishProperty.ts, 27, 1)) +>TestUndefined : Symbol(TestUndefined, Decl(expandoFunctionNullishProperty.ts, 22, 1)) + + function inner() {} +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 29, 48)) + + inner.prop = undefined; +>inner.prop : Symbol(inner.prop, Decl(expandoFunctionNullishProperty.ts, 30, 21)) +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 29, 48)) +>prop : Symbol(inner.prop, Decl(expandoFunctionNullishProperty.ts, 30, 21)) +>undefined : Symbol(undefined) + + return inner; +>inner : Symbol(inner, Decl(expandoFunctionNullishProperty.ts, 29, 48)) +} + diff --git a/tests/baselines/reference/expandoFunctionNullishProperty.types b/tests/baselines/reference/expandoFunctionNullishProperty.types new file mode 100644 index 00000000000..a368dd4bb59 --- /dev/null +++ b/tests/baselines/reference/expandoFunctionNullishProperty.types @@ -0,0 +1,72 @@ +//// [tests/cases/compiler/expandoFunctionNullishProperty.ts] //// + +=== expandoFunctionNullishProperty.ts === +// mentioned in https://github.com/microsoft/TypeScript/issues/54220 + +interface TestNull { + (): void; + readonly prop: null; +>prop : null +} + +export function testNull(): TestNull { +>testNull : () => TestNull + + function inner() {} +>inner : { (): void; prop: null; } + + inner.prop = null; +>inner.prop = null : null +>inner.prop : null +>inner : { (): void; prop: null; } +>prop : null + + return inner; +>inner : { (): void; prop: null; } +} + +interface TestNull2 { + (): void; + prop: string | null; +>prop : string | null +} + +export function testNull2(): TestNull2 { +>testNull2 : () => TestNull2 + + function inner() {} +>inner : { (): void; prop: null; } + + inner.prop = null; +>inner.prop = null : null +>inner.prop : null +>inner : { (): void; prop: null; } +>prop : null + + return inner; +>inner : { (): void; prop: null; } +} + +interface TestUndefined { + (): void; + readonly prop: undefined; +>prop : undefined +} + +export function testUndefined(): TestUndefined { +>testUndefined : () => TestUndefined + + function inner() {} +>inner : { (): void; prop: undefined; } + + inner.prop = undefined; +>inner.prop = undefined : undefined +>inner.prop : undefined +>inner : { (): void; prop: undefined; } +>prop : undefined +>undefined : undefined + + return inner; +>inner : { (): void; prop: undefined; } +} + diff --git a/tests/cases/compiler/expandoFunctionNullishProperty.ts b/tests/cases/compiler/expandoFunctionNullishProperty.ts new file mode 100644 index 00000000000..cbfda53e9a5 --- /dev/null +++ b/tests/cases/compiler/expandoFunctionNullishProperty.ts @@ -0,0 +1,38 @@ +// @strict: true +// @target: esnext +// @declaration: true + +// mentioned in https://github.com/microsoft/TypeScript/issues/54220 + +interface TestNull { + (): void; + readonly prop: null; +} + +export function testNull(): TestNull { + function inner() {} + inner.prop = null; + return inner; +} + +interface TestNull2 { + (): void; + prop: string | null; +} + +export function testNull2(): TestNull2 { + function inner() {} + inner.prop = null; + return inner; +} + +interface TestUndefined { + (): void; + readonly prop: undefined; +} + +export function testUndefined(): TestUndefined { + function inner() {} + inner.prop = undefined; + return inner; +}