Let's assume I have these 2 types:
type Foo = {
foo: string
}
type Bar = {
bar: number
}
Is there a way to type individual fields of an object literal (I'm looking for the right syntax if it exists), without creating a wrapper type?
This is what I want to avoid:
type Wrapper = {
a: Foo
b: Bar
}
const x: Wrapper = {
a: { foo: 'foo' },
b: { bar: 123 }
}
This is what I'm trying to do:
const x = {
// x.a should be of type Foo, enforced by the compiler
a: { foo: 'foo' },
// x.b should be of type Bar, enforced by the compiler
b: { bar: 123 }
}
What I considered, but is not suitable:
- Using a
Record
type makes no sense, as I lose the individual fields and their individual types:
const x: Record<string, Foo | Bar> = {
a: { foo: 'foo' },
b: { bar: 123 }
}
- Type casting (or whatever its called in TS) is also not suitable, as now I loose compiler checks and content assist. At least with this version the type of
x
is correct:
const x = {
a: { foo: 'foo' } as Foo,
b: { bar: 123 } as Bar
}
CodePudding user response:
It seems like you are looking for the satisfies
operator which will be rolled out in TypeScript 4.9. It allows to preserve the literal type while still type checking with some constraint.
const x = {
a: { foo: "223" },
b: { bar: 123 }
} satisfies Record<string, Foo | Bar>
x.a.foo // string
x.b.bar // number