Skip to content

Typescript ignores prototype of object literals assigned to index signatures #37963

Closed
@mike-marcacci

Description

@mike-marcacci

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions