0

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.

Playground

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.

1 Answer 1

1

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
}

playground.

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

Comments

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.