// This is what I tried, but did not work
function useAccordion<T extends Readonly<Array<string>>>(keys:T,defaultOpenKey: T[number]){
// ...
}
useAccordion(["panel1","panel2","panel3"], "panel1") // 2nd argument has to be one of the element from the keys(first argument)
useAccordion(["panel1","panel2","panel3"], "panel7") // It should throw a typescript error
note: as const
type assertion works but can't figure out how to set the type assertion in the function argument.
e.g.
const KEYS = [
"panel1","panel2","panel3"
] as const
const initialOpen:typeof KEYS[number] = "panel1" // correct
const initialOpen:typeof KEYS[number] = "panel8" // Error
The question is how can I do the same thing inside a function args.
Thanks
CodePudding user response:
You can pass your type KEYS
into the generic of useAccordion
which will help you to correct types on that function's params.
const KEYS = [
"panel1","panel2","panel3"
] as const
function useAccordion<T extends Readonly<Array<string>>>(keys:T,defaultOpenKey: T[number]){
// ...
}
useAccordion<typeof KEYS>(["panel1","panel2","panel3"], "panel1") // 2nd argument has to be one of the element from the keys(first argument)
useAccordion<typeof KEYS>(["panel1","panel2","panel3"], "panel7") // It should throw a typescript error
CodePudding user response:
One method to achieve this would be to map the values in the array to a union type of the values in the array.
type ValueInArray<T extends unknown[]> = T extends [unknown, ...infer R] ? T[0] | ValueInArray<R> : never;
const a: ValueInArray<["a"]> = "a";
const b: ValueInArray<["a"]> = "b"; // error
const c: ValueInArray<["a", "b", "c"]> = "c";
const d: ValueInArray<["a", "b", "c"]> = "d"; // error
Check it out on the Playground.