Closed dwelle closed 5 months ago
In a lot of ways, changing the type is already fairly similar to what default parameters already do:
declare const o: { x?: number };
const { x=3 } = o;
// x is number here, not number|undefined
Obviously removing undefined
from a type is a lot narrower than generally changing the type, but I don't think it's too surprising.
In fact one could even model a default value as an extractor:
const default3 = {
[Symbol.matcher](v: number|undefined): number {
return { matched: true, value: v ?? 3 };
}
}
const { x: default3(x) } = o;
In TypeScript, we could make inference aware of the inverse relationship between an extractor return type and its input argument:
const toDateObject = {
[Symbol.customMatcher](subject: number | string | Date): [Date] | false {
const result = subject instanceof Date ? result : new Date(subject);
return !isNaN(result.valueOf()) && [result];
}
};
function f({ createdAt: toDateObject(createdAt) }) {
return createdAt;
}
Here, we would infer Date
for createdAt
inside of f
, and { createdAt: number | string | Date }
for f
's first parameter.
Also, there is a typo in your example that may be the source of confusion here:
class Book {
public createdAt: Date;
constructor({
- toDateObject(createdAt)
+ createdAt: toDateObject(createdAt)
}: {
createdAt: number
}) {
this.createdAt = createdAt // createdAt is a Date object at this point
}
}
In TypeScript and other type systems, as I understand, the parameter/argument type would need to be different from the value type in the function body for example, where the type would come from the extractor's return value.
I'm not seeing any blockers here, but might be a bit confusing.