Add ValueModule as a valid object literal type, as they are immutable (#19090)

* Add ValueModule as a valid object literal type, as they are immutable

* Rename method based on usage
This commit is contained in:
Wesley Wigham 2017-10-11 15:13:33 -07:00 committed by GitHub
parent 9f4130b204
commit b949245336
5 changed files with 94 additions and 5 deletions

View file

@ -6274,7 +6274,7 @@ namespace ts {
}
function getImplicitIndexTypeOfType(type: Type, kind: IndexKind): Type {
if (isObjectLiteralType(type)) {
if (isObjectTypeWithInferableIndex(type)) {
const propTypes: Type[] = [];
for (const prop of getPropertiesOfType(type)) {
if (kind === IndexKind.String || isNumericLiteralName(prop.escapedName)) {
@ -9831,7 +9831,7 @@ namespace ts {
// if T is related to U.
return kind === IndexKind.String && isRelatedTo(getTemplateTypeFromMappedType(<MappedType>source), targetInfo.type, reportErrors);
}
if (isObjectLiteralType(source)) {
if (isObjectTypeWithInferableIndex(source)) {
let related = Ternary.True;
if (kind === IndexKind.String) {
const sourceNumberInfo = getIndexInfoOfType(source, IndexKind.Number);
@ -10344,11 +10344,11 @@ namespace ts {
}
/**
* Return true if type was inferred from an object literal or written as an object type literal
* Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module
* with no call or construct signatures.
*/
function isObjectLiteralType(type: Type) {
return type.symbol && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral)) !== 0 &&
function isObjectTypeWithInferableIndex(type: Type) {
return type.symbol && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.ValueModule)) !== 0 &&
getSignaturesOfType(type, SignatureKind.Call).length === 0 &&
getSignaturesOfType(type, SignatureKind.Construct).length === 0;
}

View file

@ -0,0 +1,28 @@
//// [tests/cases/compiler/inferredIndexerOnNamespaceImport.ts] ////
//// [foo.ts]
export const x = 3;
export const y = 5;
//// [bar.ts]
import * as foo from "./foo";
function f(map: { [k: string]: number }) {
// ...
}
f(foo);
//// [foo.js]
"use strict";
exports.__esModule = true;
exports.x = 3;
exports.y = 5;
//// [bar.js]
"use strict";
exports.__esModule = true;
var foo = require("./foo");
function f(map) {
// ...
}
f(foo);

View file

@ -0,0 +1,23 @@
=== tests/cases/compiler/foo.ts ===
export const x = 3;
>x : Symbol(x, Decl(foo.ts, 0, 12))
export const y = 5;
>y : Symbol(y, Decl(foo.ts, 1, 12))
=== tests/cases/compiler/bar.ts ===
import * as foo from "./foo";
>foo : Symbol(foo, Decl(bar.ts, 0, 6))
function f(map: { [k: string]: number }) {
>f : Symbol(f, Decl(bar.ts, 0, 29))
>map : Symbol(map, Decl(bar.ts, 2, 11))
>k : Symbol(k, Decl(bar.ts, 2, 19))
// ...
}
f(foo);
>f : Symbol(f, Decl(bar.ts, 0, 29))
>foo : Symbol(foo, Decl(bar.ts, 0, 6))

View file

@ -0,0 +1,26 @@
=== tests/cases/compiler/foo.ts ===
export const x = 3;
>x : 3
>3 : 3
export const y = 5;
>y : 5
>5 : 5
=== tests/cases/compiler/bar.ts ===
import * as foo from "./foo";
>foo : typeof foo
function f(map: { [k: string]: number }) {
>f : (map: { [k: string]: number; }) => void
>map : { [k: string]: number; }
>k : string
// ...
}
f(foo);
>f(foo) : void
>f : (map: { [k: string]: number; }) => void
>foo : typeof foo

View file

@ -0,0 +1,12 @@
// @filename: foo.ts
export const x = 3;
export const y = 5;
// @filename: bar.ts
import * as foo from "./foo";
function f(map: { [k: string]: number }) {
// ...
}
f(foo);