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?
CodePudding user response:
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:
CodePudding user response:
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";
// }
CodePudding user response:
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'>;