Why Typescript cannot infer discriminated types when destructing

Viewed 34

I try in vain to narrow discriminated types with object destructuring. I thought Typescript is able to infer them since v4.4.

However, I cannot do it in this code (just an example of idea):

type WritableRecord = {
    someField: 'a'
}

type ReadonlyRecord = {
    otherField: 'b'
}

type Writable = {
    readonly: false;
} & WritableRecord;

type Readonly = {
    readonly: true;
} & ReadonlyRecord;

export type RecordProps = Readonly | Writable

type Fn = (props: RecordProps) => void

const fn: Fn = ({ readonly, ...props }) => {
    switch (readonly) {
        case true:
            const readonlyCheck: ReadonlyRecord = props

            break;
        case false:
            const writableCheck: WritableRecord = props
            break
    }
}

But without destructuring it works:

type WritableRecord = {
    someField: 'a'
}

type ReadonlyRecord = {
    otherField: 'b'
}

type Writable = {
    readonly: false;
} & WritableRecord;

type Readonly = {
    readonly: true;
} & ReadonlyRecord;

export type RecordProps = Readonly | Writable

type Fn = (props: RecordProps) => void

const fn: Fn = (props) => {
    switch (props.readonly) {
        case true:
            {
                const { readonly, ...readonlyProps } = props
                const readonlyCheck: ReadonlyRecord = readonlyProps
                break;
            }


        case false:
            {
                const { readonly, ...writableProps } = props
                const writableCheck: WritableRecord = writableProps
                break;
            }
    }
}

Maybe, I get v4.4 announcement wrong, or is there an error?

1 Answers

You've just discovered that currently (as of TS4.7) there's no support for control flow analysis for destructured rest elements. This is a known missing feature of TypeScript, requested at microsoft/TypeScript#46680.

If you want to see this supported you might want to go to that issue and give it a , but it probably won't have much effect one way or the other. For now you probably need to destructure the rest element only after checking the discriminant property, as you've done in your second example.

Related