#I want a variable's val to be a subset of an interface's functions. Max type safety, how?

15 messages · Page 1 of 1 (latest)

teal epochBOT
#
sleepeasysoftware#0

Preview:```ts
interface AssertionApi<T> {
ok: () => T
notOk: () => T
contains: (s: string) => T
notContains: (s: string) => T
}

type AssertBooleanFunction = Extract<
keyof AssertionApi<boolean>,
"ok" | "notOk" | "foo"

// ^?

const usingOk: AssertBooleanFunction = "ok"
...```

maiden needle
#

!ts

teal epochBOT
#
interface AssertionApi<T> {
  ok: () => T;
  notOk: () => T;
  contains: (s: string) => T;
  notContains: (s: string) => T;
}

type AssertBooleanFunction = Extract<keyof AssertionApi<boolean>, 'ok' | 'notOk' | 'foo'>;
//   ^? - type AssertBooleanFunction = "ok" | "notOk"

const usingOk: AssertBooleanFunction = 'ok';
const usingFoo: AssertBooleanFunction = 'foo'; // error!
//    ^^^^^^^^
// Type '"foo"' is not assignable to type 'AssertBooleanFunction'.

maiden needle
#

This seems pretty good to me, but if I misspelled 'notOk' when defining AssertBooleanFunction, I wouldn't get a compile error. To look at it another way, Extract lets me refer to properties that don't exist in the interface, like 'foo'.

Is this the best type safety I can get, or should I be doing something better?

Ultimately, my goal is to leverage the type system as much as possible if I need to refactor the interface.

halcyon nacelle
#

It's unclear to me what errors you are trying to prevent

#

Are you trying to make sure the keys in Extract must be in sync with AssertionApi?

maiden needle
#

Typos/impossible values for these string literals:

type AssertBooleanFunction = Extract<keyof AssertionApi<boolean>, 'ok' | 'notOk' | 'foo'>;
halcyon nacelle
#

Well, a simple solution is to do:

type SafeExtract<T, K extends keyof T> = K

And use SafeExtract<AssertionApi<boolean>, ...>.

maiden needle
#

Gotcha

halcyon nacelle
#

As a side note, in most cases Extract<T, U> is the same as T & U.

maiden needle
halcyon nacelle
#

Extract is implemented as a conditional type so there are some shenanigans with deferred evaluation that matters in edge cases.

maiden needle
#

I'm not sure if I'm advanced enough to truly understand that, but I like the way T & U looks. Would you recommend one over the other?

halcyon nacelle
#

I think the difference between the two are minor enough that you can pick whichever you like more. Personally I go with T & U.

maiden needle
#

Thanks @halcyon nacelle