I apologize for the poor title, but I don't have the vocabulary to word it better. Let me show you my code:
type Foo = "bar" | "baz";
type Consistency = {
[K in Foo]: {
foo: K;
fooTemplate: `${K} in a template`;
}
}[Foo]
// I want this to compile (and it does)
const valid1: Consistency = {
foo: "bar",
fooTemplate: "bar in a template",
}
const valid2: Consistency = {
foo: "baz",
fooTemplate: "baz in a template",
}
export const anFoo: Foo = "bar"
const valid3: Consistency = {
foo: anFoo,
fooTemplate: `${anFoo} in a template` as const
}
export interface MyObj {
temporary: {
myProperty: Foo;
};
}
const state: MyObj = {
temporary: {
myProperty: "bar"
}
}
const i: Foo = state.temporary.myProperty;
const valid4: Consistency = { // Why doesn't this one compile????
foo: i,
fooTemplate: `${i} in a template` as const
}
// I don't want this to compile (and it doesn't)
const invalid1: Consistency = {
foo: "bar",
fooTemplate: "baz in a template",
}
const invalid2: Consistency = {
foo: "baz",
fooTemplate: "bar in a template",
}
You can play with this here. This all works the way I expect accept for valid4. For some reason, valid4 doesn't compile, and I want it to. Why isn't it compiling and how do I make it compile?
The answer doesn't explicitly say this so I will: There's no solution to this problem.
iand you as the author know that it's the sameiin both places, but TS is just looking atias typeFoo. It is possible to have a typeFooin both places and not be assignable toConsistencyif oneFoois"bar"and the otherFoois"baz". so the typeFoocannot guarantee assignability.anFoois typed as"bar"and not asFoo.declare const anFoo: Foodoesn't work either.