skip to Main Content

I need to create a new object from a source that is a union of object type.

TypeScript does not manage to infer the typing of the new object as a union.

Any idea how to solve this issue or if it is a limitation of TypeScript?

Here is a quick example to understand the issue:

I could do a switch case or write manually the return type but I want a modular code that does not require changes when adding a new source type.

Playground link / Bug report link

type Source = {
    type: 'ws'
    reader: {state: 'connecting'}
} | {
    type: 'file'
    reader: {state: number}
}

let source: Source = {type: 'file', reader:  {state: 12}}

/*
 * Error: getSourceWithState return type is 
 * {
 *   type: "ws" | "file";
 *   state: "connecting" | number;
 * } 
 * instead of
 *  {
 *   type: "file";
 *   state: number;
 * } |
 *  {
 *   type: "ws";
 *   state: "connecting";
 * } 
 */
const getSourceWithState = () => {
    return {
        type: source.type,
        state: source.reader.state
    }
}

const sourceWithState = getSourceWithState()
if (sourceWithState.type === 'file') {
    // Error
    sourceWithState.state += 1
}

2

Answers


  1. Use multiple returns

    
    const getSourceWithState = () => {
        if (source.type === 'file') {
            return {
                type: source.type,
                state: source.reader.state
            }
        } else {
            return {
                type: source.type,
                state: source.reader.state
            }
        }
    }
    

    (well, you can also define the return type but I guess you don’t want that)

    Login or Signup to reply.
  2. Try this

    type SourceType = "ws" | "file"
    type SourceReaderState = "connecting" | number;
    type Source = {
       type: SourceType,
       reader: {state: SourceReaderState}
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search