Description
Suggestion
Properties generators [Ed: Mapped types] require separate type definition. Is this really a requirement by design limitations? It's weird for me that I must to merge two types to get type I actually want. Also, depending on where the [foo in Foos]: Bar
part is placed, it gives two different, but both hard to understand error - it would be nice to have easy to understand error at least, even if separate type is required.
🔍 Search Terms
Properties generation. Mapped types.
✅ Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
⭐ Suggestion
Make properties generator thing work if it's amongst other properties. There should be check that generated property names are other than properties defined alongside.
If not possible (due to design limitations or something), make it return easy to understand error.
📃 Motivating Example
The 17th line } & {
seems just a burden.
export type PricingSpans = {
/// Pricing for day/hour if up to `days` days.
[days: number]: number;
/// Pricing for day/hour if more days than specified
above: number;
}
export const PlaceTypes = ['openSky', 'roofed', 'garage'] as const;
export type PlaceType = (typeof PlaceTypes)[number];
type PricingInfo = {
/// Pricing spans for various place types
[placeType in PlaceType]: PricingSpans;
// Removing next line makes it fail, weird...
} & {
/// Pricing model
model: 'hour' | 'day';
}
//------------------------------------------------------
const foo: PricingInfo = {
openSky: {
0: 40,
above: 30
},
roofed: {
0: 50,
above: 40
},
garage: {
0: 80,
above: 70
},
model: 'day',
}
Output
export const PlaceTypes = ['openSky', 'roofed', 'garage'];
//------------------------------------------------------
const foo = {
openSky: {
0: 40,
above: 30
},
roofed: {
0: 50,
above: 40
},
garage: {
0: 80,
above: 70
},
model: 'day',
};
Compiler Options
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"alwaysStrict": true,
"esModuleInterop": true,
"declaration": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2017",
"jsx": "react",
"module": "ESNext",
"moduleResolution": "node"
}
}
Playground Link: Provided
Other examples:
- Weird errors generated if the property generator part is placed after any other properties: Playground Link
- Other weird error generated if the property generator part is placed first (before any other properties): Playground Link
💻 Use Cases
Its not important issue. Its just quality of life, something rarely used could look a bit better. Workaround is just separate the property generator and join with others. What's nice about the workaround is that it report error if properties generated overlap with properties defined attached (i.e, you can add 'model'
into PlaceTypes
, and there is proper error).