discriminated union, variant, mapped types
We can get a property type from object without any surprise:
type Payload = { foo: string }
type Foo = Payload['foo'] // string
But if the object is a discriminated union, we can only get a type of a member that repeats on all variants
type Payload = (
{
result: 'success'
data: number
} |
{
result: 'error'
errorCode: 'invalid-token' | 'expired-token'
}
)
type Errors = Payload[ ???? ] // we can't =(
The only way at this moment is extracting the type into a new one:
type PayloadError = 'invalid-token' | 'expired-token'
type Payload = (
{
result: 'success'
data: number
} |
{
result: 'error'
errorCode: PayloadError
}
)
type Errors = PayloadError
Extracting a type from a variant has two problems:
Payload['foo'] instead of creating a Foo type)I really don't know how could be the syntax. Maybe could be something like
type PayloadError = Payload['result'] when 'error'
type Errors = (Payload['result'] when 'error')['errorCode']
The suggestion https://github.com/microsoft/TypeScript/issues/39103 is similar, but for a different use case.
I'm suggesting to get the variant type _outside_ of the declaration, and this suggestion want to get the variant type _inside_ of the type + ternary operator in order to write some shortcuts on the declaration type.
My suggestion meets these guidelines:
You can do this already with conditional types:
type OfResult<T extends { result: string }, K extends string> = T extends { result: K } ? T : never
type Errors = OfResult<Payload, 'error'>['errorCode']
Or like this:
type Errors = (Payload & { result: "error" })["errorCode"];
I didn't know that it's possible with these approaches. Thanks.
I'm closing my issue because I think that will be overengineering adding my suggestion, that will be just a syntax sugar .
Most helpful comment
Or like this: