简体   繁体   中英

Define a type with a subset of an object keys

I wonder how to create a type that has only a subset of keys from an object, imagine the following object:

const something = {
  cannary: "yellow",
  coyote: "brown",
  fox: "red",
  roses: "white",
  tulipan: "purple",
  palmera: "green"
}

If I defined a type like:

type Something = keyof typeof something

Autocomplete and the check type will work for all the keys, but what about if I want to accept only some of those keys like:

type Animal = keyof typeof {only cannary|coyote|fox} 

is this feasible to do in typescript?

The built-in Extract<T, U> type is a good candidate for this. It will...

Extract from T those types that are assignable to U

However, in your case, this still allows

Extract<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

to pass, even though 'monkey' does not exist in T .

A small modification to the Extract<T, U> type from:

type Extract<T, U> = T extends U ? T : never;

to

type ExtractExact<T, U extends T> = T extends U ? T : never;

forces the consumer to supply a type for U that must extend T .

Now:

type CausesTypeError = ExtractExact<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

will show up immediately in the IDE as something unintended:

在此处输入图像描述

Playground Link

As @spender pointed out, Extract will "extract" members from a set, and can be used to meet your request.

You can also use Pick

type AnimalsPicked = keyof Pick<typeof something, 'cannary' | 'coyote' | 'monkey'>
type AnimalsExtracted = Extract<keyof typeof something, 'cannary' | 'coyote' | 'monkey'>

Same result.

If you want the intermediate object type

type AnimalsObj = Pick<typeof something, 'cannary' | 'coyote' | 'monkey'>

Because you haven't actually described the larger problem you trying to solve, the following might or might not be helpful.

const something = {
  cannary: "yellow",
  coyote: "brown",
  fox: "red",
  roses: "white",
  tulipan: "purple",
  palmera: "green"
} as const;
const animals = (()=>{
   const {cannary,coyote,fox} = something;
   return {cannary,coyote,fox};
})();
// UI shows
// const animals: {
//   cannary: "yellow";
//   coyote: "brown";
//   fox: "red";
// }

playground

You can use Pick<T> utility type

https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys

const something = {
  cannary: 'yellow',
  coyote: 'brown',
  fox: 'red',
  roses: 'white',
  tulipan: 'purple',
  palmera: 'green',
};

// type Something = "cannary" | "coyote" | "fox" | "roses" | "tulipan" | "palmera"
type Something = keyof typeof something;

// type Animal = "cannary" | "coyote" | "fox"
type Animal = keyof Pick<typeof something, 'cannary' | 'coyote' | 'fox'>;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM