#Exhaustiveness checking of type

25 messages · Page 1 of 1 (latest)

wispy rapids
#

Is there a way I can ensure a union type is exhaustive with all the values of a type union instead of an array?

For example, this is the goal:

type keys = 'a' | 'b' | 'c'

type map = {
  key: 'a',
} | {
  key: 'b'
}
// ^ This should error because it's missing an object with a key of 'c'

Playground link: https://www.typescriptlang.org/play?#code/C4TwDgpgBA1hIGcoF4oHICGaoB90CNs80BjNAKHNEigFsMwUoBvcqWeALnSwBpyAvrhZsOIbmkKDyAehlQAelAAqACwCWSBKoD2AVwA2AEygQATmZ1mo+CCQx6E0dcDRJamhOoB2AcygY3lA6+ABWdsBQAO4uqgFiwQBm6GRAA

umbral scrollBOT
#

@wispy rapids Here's a shortened URL of your playground link! You can remove the full link from your message.

JosNun#8739

Preview:```ts
type keys = "a" | "b" | "c"

type map =
| {
key: "a"
}
| {
key: "b"
}
// ^ This should error because it's missing an object with a key of 'c'```

ornate rampart
#

you could use validation types for that, but for this case why not just use the union directly? or is your usecase different?

wispy rapids
#

I'm not familiar with validation types... Could you elaborate?

In my case, the union is derived from const objects, and there's a few operations being performed on them to extract the keys I want to use from these objects

ornate rampart
#

have you tried looking into using satisfies on the const object?

wispy rapids
#

In my case, there's multiple const objects that are being combined into the keys variable

ornate rampart
#

about validation types, not sure it's the right term, but it's this kind of pattern:

umbral scrollBOT
#
type X = number;
{
  interface IncludesString<T extends string> {}
  type _T = IncludesString<X>
//                         ^
// Type 'number' does not satisfy the constraint 'string'.
}
wispy rapids
wispy rapids
ornate rampart
#

it's not a common pattern afaik, but it is a thing

wispy rapids
#

Though, I'm still not sure how to use that pattern to ensure that a given type has a key for every value of a union type?

ornate rampart
#

i wouldn't recommend it or recommend against it, but it's a thing

ornate rampart
wispy rapids
#

Ensuring that it extends it, and ensuring that it exhaustively extends it is two different problems though, right?

ornate rampart
#

i think in this position they're the same

#

wait no?

#

give me a sec to think

#

oh yeah it'd be in the other direction

umbral scrollBOT
#

@wispy rapids Here's a shortened URL of your playground link! You can remove the full link from your message.

JosNun#8739

Preview:```ts
type Keys = "a" | "b" | "c"

type KeyMap =
| {
key: "a"
}
| {
key: "b"
}
// ^ This should error because it's missing an object with a key of 'c'

interface ExhaustivenessCheck<
TMap extends {key: Keys}

{}

type _Check = ExhaustivenessCheck<KeyMap>```

umbral scrollBOT
#

@wispy rapids Here's a shortened URL of your playground link! You can remove the full link from your message.

JosNun#8739

Preview:```ts
type Keys = "a" | "b" | "c"

type KeyMap =
| {
key: "a"
}
| {
key: "b"
}
// ^ This should error because it's missing an object with a key of 'c'

interface ExhaustivenessCheck<
TObject extends {key: unknown},
TKey extends TObject["key"]

{}

type _Check = ExhaustivenessCheck<KeyMap, Keys>
...```

ornate rampart
#

that looks about right to me

wispy rapids
#

Which seems to work alright. Now I just gotta figure out how to port it to my case where the key is an array of strings instead of a string 😆