0

To illustrate what I'm looking for:

interface Thing {
  id: string
  name: string
  amount: number
}

type OtherProps = string[] // What goes in here instead of `string[]`?

function processOtherProps(props: OtherProps) {
  throw new Error("unimplemented")
}

processOtherProps(["someOtherProp"]) // Ok
processOtherProps(["name"]) // Compiler error because "name" is a key of Thing
processOtherProps(["someOtherProp", "amount"]) // Compiler error because "amount" is a key of Thing

How do I declare OtherProps in a way that produces the expected outputs in the last three lines?

3
  • 1
    There is no specific type that works how you want; negated types do not exist in TypeScript. You’ll need to make processOtherProps generic. On mobile now so if I don’t get to it I’m sure someone else will explain. Good luck! Commented Mar 12, 2022 at 16:34
  • Is it no possible through a combination of the conditional operator ` ? : ` and the type never? I tried this for a while but couldn't figure out myself Commented Mar 12, 2022 at 16:43
  • No, there is no specific type in TypeScript like "all string except keyof Thing". Conditional types do not give you this. Had negated types as in ms/TS#29317 been implemented, you could have written string & not keyof Thing. You can use generic types, but it would require something like type OtherProps<K extends string> = Exclude<K, keyof Thing>[] and then you carry K around everywhere, like this. If you want me to write that up as an answer, let me know (although the existing answer is similar) Commented Mar 12, 2022 at 22:39

1 Answer 1

1

You can do this via a generic function as @jcalz stated. Basically, you can take in a generic array that must be readonly (via as const) then make sure none of the values in the array are keys in Thing.

interface Thing {
  id: string
  name: string
  amount: number
}

function processOtherProps<T extends readonly string[]>(props: T[number] extends Exclude<T[number], keyof Thing> ? T : never) {
  throw new Error("unimplemented")
}

processOtherProps(["someOtherProp"] as const) // Ok
processOtherProps(["name"] as const) // Compiler error because "name" is a key of Thing
processOtherProps(["someOtherProp", "amount"] as const) // Compiler error because "amount" is a key of Thing

TypeScript Playground Link

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.