Reputation: 12176
I have the following code which won't compile with TypeScript compiler 3.7.3
type Fruit = 'apple' | 'banana'
const val = 'apple'
// Works. TS remembers the value of `val`
const fruit: Fruit = val
type Basket = {
fruit: Fruit
}
const obj = {
fruit: 'apple'
}
// Error: Type 'string' is not assignable to type 'Fruit'.
// TS probably discarded that `fruit` property has concrete value and treats it as any `string`.
const structuralBasket: Basket = obj
// This works
const declaredBasket: Basket = {
fruit: 'apple'
}
I need the obj
to stay as is. What I cannot do and not looking for in the answer:
obj
as a Basket
Is this a limitation of TypeScript compiler?
If so, is there workaround ? Will this be addressed in the future ?
Upvotes: 2
Views: 449
Reputation: 20162
The problem is that when you just declare obj
its gets a wider type then Fruit
is, so what you got is {fruit: string}
, what is naturally not assignable to its sub-type. You can add as const
const obj = {
fruit: 'apple'
} as const
And such construct will be inferred as {fruit: 'apple'}
, what is already assignable to Basket
being its subtype.
You can also create such objects by value constructors. Consider:
const makeBasket = (fruit: Fruit): Basket => ({fruit})
const obj = makeBasket('apple'); // Basket object
Upvotes: 2