Can I define a generic type constraint on DU Keys?

61 views Asked by At

Is there a way to define a generic type constraint such that

//this will compile
type Contrained = StrongConstraint<"a" | "b" | "c", "a" | "b">

//this wont compile as "a" | "b" | "d" is not a strict subset of "a" | "b" | "c"
type Contrained = StrongConstraint<"a" | "b" | "c", "a" | "b" | "d">

This is similar to Exclude just stronger as I dont like keys in the second param that are not part of the first.

2

There are 2 answers

0
MoxxiManagarm On

I don't think your approach is possible (at least not that I am aware of). However, depending on your UseCase you could check about Partial.

type StrongConstraint<T> = {
    left: T,
    right: Partial<T>,
}

// success
const foo: StrongConstraint<'a' | 'b' | 'c'> = {
    left: 'a',
    right: 'b'
}

// fail
const bar: StrongConstraint<'a' | 'b' | 'c'> = {
    left: 'a',
    right: 'd'
}
0
ccarton On

You can force the second parameter to extend the first:

type ExcludeConstrained<T, U extends T> = Exclude<T, U>

type T1 = ExcludeConstrained<"a" | "b" | "c", "a" | "b">; // OK, T1 = 'c'

type T2 = ExcludeConstrained<"a" | "b" | "c", "a" | "b" | "d">; // ERROR
// -----------------------------------------> ~~~~~~~~~~~~~~~
// Error: Type '"d"' is not assignable to type '"a" | "b" | "c"'