3

I have this map function that is rendering the type of an object.

function mapStuffs(fields: any) {
    switch (fields.type) {
        case "NewStuffs":
            return {
                type: "NewStuffs" as const,
                stuff: fields.stuff
            };
        case "StuffFile":
            const fileName = "jadflkjs";
            const stuffId = "adlkajsf";
            return {
                type: "StuffFile" as const,
                fileName,
                stuffId
            };
        default:
            return {
                type: "ExistingStuff" as const
            };
    }
}

And when I build, the generated type is:

mainstuff:
        | {
              stuff: string | undefined;
              type: "NewStuffs";
              fileName?: undefined;
              stuffId?: undefined;
          }
        | {
              type: "StuffFile";
              fileName: string;
              stuffId: string;
          }
        | {
              type: "ExistingStuff";
              fileName?: undefined;
              stuffId?: undefined;
          };

I don't understand how to remove fileName and stuffId as optional parameters when they're not required. Is it a typescript bug? What I would like to have is this type:

mainstuff:
        | {
              stuff: string | undefined;
              type: "NewStuffs";
          }
        | {
              type: "StuffFile";
              fileName: string;
              stuffId: string;
          }
        | {
              type: "ExistingStuff";
          };
0

1 Answer 1

2

It's not a TypeScript bug. This is the intended behavior since TypeScript 2.7 introduced improved type inference for object literals. The fact that fileName and stuffId is not being included for some of the return values makes the compiler think that absence should be reflected in the return type.

The type inference algorithm in TypeScript is a set of heuristics, where the language designers try to guess what kinds of things most people want to see in certain circumstances. If you don't like the inferred type, you are free to annotate the return type of your mapStuffs() function with whatever type you prefer, and the compiler will be happy with this, assuming your function implementation conforms to it:

type MappedStuff = {
    stuff: string | undefined;
    type: "NewStuffs";
} | {
    type: "StuffFile";
    fileName: string;
    stuffId: string;
} | {
    type: "ExistingStuff";
};

function mapStuffs(fields: any): MappedStuff {

    switch (fields.type) {
        case "NewStuffs":
            return {
                type: "NewStuffs" as const,
                stuff: fields.stuff
            };
        case "StuffFile":
            const fileName = "jadflkjs";
            const stuffId = "adlkajsf";
            return {
                type: "StuffFile" as const,
                fileName,
                stuffId
            };
        default:
            return {
                type: "ExistingStuff" as const
            };
    }
}

Playground link to code

Sign up to request clarification or add additional context in comments.

7 Comments

thanks a lot! now it's really clear! very helpful
but now my question is: why I don't see "stuff" attribute in the other objects?
Sorry, I’m not sure what you’re asking. Follow up questions may deserve their own posts, in any case.
sure, sorry, I was just asking why the "issue" I had was happening only with 'fileName' and 'stuffId' (attributes for type="StuffFile") and not for 'stuff' (attribute for type="NewStuffs"). But no worries, I'll open a new question
I’m not sure because the question has any for fields, but also string | undefined for fields.stuff somehow. I think I’ll need a true minimal reproducible example before I can answer (also on mobile right now so I can’t check easily at the moment)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.