Reputation: 3040
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";
};
Upvotes: 3
Views: 223
Reputation: 329258
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
};
}
}
Upvotes: 2