Ing
Ing

Reputation: 23

Typescript enum as key in specified object expected an error but had no

I have got some strange behavior of TS while work with enums as object keys. I expect TS error, but it is not, and I don't understand why.

enum List {
  sm = "sm",
  md = "md",
}

export interface Dictionary<T = any> {
  [index: string]: T;
}
export type OptionalDictionary<T, K extends string = string> = { [P in K]?: T };

type MessageType = Dictionary<string | null>;
type MessagesType = OptionalDictionary<MessageType, List>;
type Values = { receiver: List; text: string };

const values = { receiver: List.sm, text: "123" };
const { receiver, text } = values;

const data: MessagesType = {
    // [receiver]: { text }, // correct
    [receiver]: text // wrong, but no error
};

const data2: MessagesType = {};
// data2[receiver] = { text }; // correct
data2[receiver] = text; // wrong, had error

console.log(data[receiver] === data2[receiver]); // true

Sandbox

Upvotes: 2

Views: 894

Answers (1)

jcalz
jcalz

Reputation: 328362

This looks like the interaction of a few unfortunate behaviors in TypeScript.

First, computed keys of union types are widened all the way to a string index, as is the subject of microsoft/TypeScript#13948, a longstanding bug/limitation. So the type of {[receiver]: text} is seen as {[k: string]: string} instead of something like {sm: string} | {md: string}. I'm not sure when or if that will be changed, but that's what's happening.

Second, index signatures (like {[k: string]: string} are always considered assignable to weak types (types with all optional properties, like {sm?: {text: string}, md?: {text: string}}), even if the index signature's property type is incompatible with the weak type's property types! This is the subject of microsoft/TypeScript#27144, also considered a bug. Again, no idea when or if this will be addressed; it's listed as "future".

Both of those bugs put together give you the behavior you see: you're allowed to assign {[receiver]: text} to a variable of type MessagesType with no error. That's the explanation; not sure what you should do except possibly go to those two GitHub and give them a 👍?

Anyway, hope that helps; good luck!

Upvotes: 4

Related Questions