Home > front end >  Apply constraint (type/interface) for types
Apply constraint (type/interface) for types

Time:02-01

In TypeScript I am constructing a type that consists of unions of other types:

type A = B | C | D // ...

I want to want to be sure at compile time that B, C, D, etc. have the shape of a generic template so that the composite is correct. So I need kind of a interface for types or a type for a type.

For example should B "implement" Template:

type Template = { x: string; y: { [key: string]: any } };
type B = {x: "test", y: {test2: number}}

How can I solve this?

CodePudding user response:

EDIT

As @jcalz suggested you can pass a union to a generic type to check if it fits your constraint. Playground.

type Template = { x: string; y: { [key: string]: any } };
type B = { x: "B", y: { test2: number } }
type C = { x: "C", y: { test2: number } }
type D = { x: "C", y: { test2: number } }
type E = { x: 5 }

type Check<U, T extends U> = T

// @ts-expect-error
type AError1 = Check<Template, B | C | E>

// @ts-expect-error
type AError2 = Check<Template, B | C | D | E>

type A = Check<Template, B | C | D>

You can use generics for this, but it gets verbose if you want to have say more then 10 possible types in a union. Playground.

type Template = { x: string; y: { [key: string]: any } };
type B = {x: "B", y: {test2: number}}
type C = {x: "C", y: {test2: number}}
type D = {x: "C", y: {test2: number}}
type  E = {x: 5}

type MakeUnion<TBase, T1 extends TBase, T2 extends TBase, T3 extends TBase = never, T4 extends TBase = never, T5 extends TBase = never> = T1 | T2 | T3 | T4 | T5

// @ts-expect-error
type AError1 = MakeUnion<Template, B, C, E>

// @ts-expect-error
type AError2 = MakeUnion<Template, B, C, D, E>

type A = MakeUnion<Template, B, C, D>
  • Related