I want to restrict the type of one object property based on value of another property:
type DataType = "string"|"number"|"date";
type DataTypeMapping = {
"string": string;
"number": number;
"date": string;
}
interface LinkedTypesSample <T extends DataType> {
typ: T;
value: DataTypeMapping[T];
}
now I can create type checked objects like so:
const stringInstance: LinkedTypesSample<"string"> = {
typ: "string",
value: "abc"
}
const numberInstance: LinkedTypesSample<"number"> = {
typ: "number",
value: 1
}
The question is - is it possible to skip type parameter of LinkedTypesSample
?
Looks like type parameter might be inferred from typ
.
I tried to specify(naively) default type parameter like so:
interface LinkedTypesSample <T extends DataType = DataType> {
typ: T;
value: DataTypeMapping[T];
}
but in this case type checks stop work.
Edit: Ideally, I don't want 'LinkedTypesSample' to expose type parameter at all. I just want to express simple thought: one property must have certain type according to value or type of another property.
CodePudding user response:
You can try distributive conditional type. Basically create the type in two steps:
type MapType<U> = U extends DataType ? {
typ: U,
value: DataTypeMapping[U]
} : never;
type LinkedTypesSample = MapType<DataType>;
// works
const stringInstance: LinkedTypesSample = {
typ: "string",
value: "abc"
}
const numberInstance: LinkedTypesSample = {
typ: "number",
value: 1
}
// error
const stringInstance2: LinkedTypesSample = {
typ: 'string',
value: 1
}