2

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

0

1 Answer 1

4

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!

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for this deep answer, now I have understanding of this case. As solution I decide to use data as array instead of object, have some problems with concatenation feather, but TS works correctly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.