diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4dd1b7baa4431..65d20f95981bf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20621,7 +20621,8 @@ namespace ts { if (sourceInfo) { return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors); } - if (!(intersectionState & IntersectionState.Source) && isObjectTypeWithInferableIndex(source)) { + if (!(intersectionState & IntersectionState.Source) && isObjectTypeWithInferableIndex(source) && + !((relation === subtypeRelation || relation === strictSubtypeRelation) && isEmptyAnonymousObjectType(source) && !(getObjectFlags(source) & ObjectFlags.FreshLiteral))) { // Intersection constituents are never considered to have an inferred index signature return membersRelatedToIndexInfo(source, targetInfo, reportErrors); } diff --git a/tests/baselines/reference/emptyObjectNarrowing.js b/tests/baselines/reference/emptyObjectNarrowing.js new file mode 100644 index 0000000000000..f1f4aed2d1b5b --- /dev/null +++ b/tests/baselines/reference/emptyObjectNarrowing.js @@ -0,0 +1,22 @@ +//// [emptyObjectNarrowing.ts] +// Repro from #49988 + +declare function isObject(value: unknown): value is Record; +const obj = {}; +if (isObject(obj)) { + obj['attr']; +} + + +//// [emptyObjectNarrowing.js] +"use strict"; +// Repro from #49988 +var obj = {}; +if (isObject(obj)) { + obj['attr']; +} + + +//// [emptyObjectNarrowing.d.ts] +declare function isObject(value: unknown): value is Record; +declare const obj: {}; diff --git a/tests/baselines/reference/emptyObjectNarrowing.symbols b/tests/baselines/reference/emptyObjectNarrowing.symbols new file mode 100644 index 0000000000000..20015bd926ae7 --- /dev/null +++ b/tests/baselines/reference/emptyObjectNarrowing.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/emptyObjectNarrowing.ts === +// Repro from #49988 + +declare function isObject(value: unknown): value is Record; +>isObject : Symbol(isObject, Decl(emptyObjectNarrowing.ts, 0, 0)) +>value : Symbol(value, Decl(emptyObjectNarrowing.ts, 2, 26)) +>value : Symbol(value, Decl(emptyObjectNarrowing.ts, 2, 26)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +const obj = {}; +>obj : Symbol(obj, Decl(emptyObjectNarrowing.ts, 3, 5)) + +if (isObject(obj)) { +>isObject : Symbol(isObject, Decl(emptyObjectNarrowing.ts, 0, 0)) +>obj : Symbol(obj, Decl(emptyObjectNarrowing.ts, 3, 5)) + + obj['attr']; +>obj : Symbol(obj, Decl(emptyObjectNarrowing.ts, 3, 5)) +} + diff --git a/tests/baselines/reference/emptyObjectNarrowing.types b/tests/baselines/reference/emptyObjectNarrowing.types new file mode 100644 index 0000000000000..32cff0e8911f4 --- /dev/null +++ b/tests/baselines/reference/emptyObjectNarrowing.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/emptyObjectNarrowing.ts === +// Repro from #49988 + +declare function isObject(value: unknown): value is Record; +>isObject : (value: unknown) => value is Record +>value : unknown + +const obj = {}; +>obj : {} +>{} : {} + +if (isObject(obj)) { +>isObject(obj) : boolean +>isObject : (value: unknown) => value is Record +>obj : {} + + obj['attr']; +>obj['attr'] : unknown +>obj : Record +>'attr' : "attr" +} + diff --git a/tests/baselines/reference/useObjectValuesAndEntries1.types b/tests/baselines/reference/useObjectValuesAndEntries1.types index bbfd4c87d2a92..b23425aeff9a9 100644 --- a/tests/baselines/reference/useObjectValuesAndEntries1.types +++ b/tests/baselines/reference/useObjectValuesAndEntries1.types @@ -77,16 +77,16 @@ var values2 = Object.values({ a: true, b: 2 }); // (number|boolean)[] >2 : 2 var entries3 = Object.entries({}); // [string, {}][] ->entries3 : [string, unknown][] ->Object.entries({}) : [string, unknown][] +>entries3 : [string, any][] +>Object.entries({}) : [string, any][] >Object.entries : { (o: { [s: string]: T; } | ArrayLike): [string, T][]; (o: {}): [string, any][]; } >Object : ObjectConstructor >entries : { (o: { [s: string]: T; } | ArrayLike): [string, T][]; (o: {}): [string, any][]; } >{} : {} var values3 = Object.values({}); // {}[] ->values3 : unknown[] ->Object.values({}) : unknown[] +>values3 : any[] +>Object.values({}) : any[] >Object.values : { (o: { [s: string]: T; } | ArrayLike): T[]; (o: {}): any[]; } >Object : ObjectConstructor >values : { (o: { [s: string]: T; } | ArrayLike): T[]; (o: {}): any[]; } diff --git a/tests/cases/compiler/emptyObjectNarrowing.ts b/tests/cases/compiler/emptyObjectNarrowing.ts new file mode 100644 index 0000000000000..383b46535eb3d --- /dev/null +++ b/tests/cases/compiler/emptyObjectNarrowing.ts @@ -0,0 +1,10 @@ +// @strict: true +// @declaration: true + +// Repro from #49988 + +declare function isObject(value: unknown): value is Record; +const obj = {}; +if (isObject(obj)) { + obj['attr']; +}