Closed
Description
TypeScript Version: 3.8.3 & nightly 2020-04-14
Search Terms:
- Object.create
- index signatures
- prototype
Code
// This should not be possible but is:
const unsafeStringMap: { [key: string]: string } = {};
const notActuallyAString: string | undefined = unsafeStringMap['constructor'];
console.log(
`Typescript thinks this is a string (or undefined), but it's actually a ${typeof notActuallyAString}.`
);
// This is a correct implementation of the same:
const safeStringMap: { [key: string]: string } = Object.create(null);
const aString: string | undefined = safeStringMap['constructor'];
console.log(
`Typescript thinks this is a string (or undefined), and indeed it's ${typeof aString}.`
);
// Typescript seems to correctly handle this when instantiating the `Object` constructor.
const correctlyHandledStringMap: { [key: string]: string } = new Object();
// Typescript also seems to be aware of an object literal's prototype chain for other purposes.
const foo: { constructor: typeof Object.prototype.constructor } = {}
Expected behavior:
Assigning {}
to { [key: string]: string }
should fail, because it does not have a compatible signature. In javascript, an "object literal" {}
is equivalent to new Object()
and TS should treat it accordingly.
Actual behavior:
TS allows the assigning of {}
to { [key: string]: string }
, leading to runtime crashes and potential security issues (including prototype pollution) when a key with the same name as a member of Object.prototype
(constructor
, __proto__
, etc) is accessed or set.
Playground Link:
Link
Related Issues:
#13778