如何在TypeScript中缩小可选值的类型范围?
解决TypeScript中根据text属性精准收窄value类型的问题
问题核心是Array.prototype.find的默认回调无法让TypeScript自动识别返回的是联合类型中的特定成员,需要通过类型守卫帮TS明确类型。
两种实现方式:
方式一:自定义可复用的类型守卫函数
先定义一个通用的类型守卫,用来判断选项的text属性是否匹配指定值,同时告诉TS对应的类型:
function isSelectOptionWithText<T extends SelectOption['text']>( option: SelectOption, text: T ): option is Extract<SelectOption, { text: T }> { return option.text === text; }
然后在find中调用这个函数:
const numberValue = options?.find(option => isSelectOptionWithText(option, 'b'))?.value;
此时numberValue的类型会被自动收窄为number | undefined。
方式二:直接在find回调中使用类型谓词
如果不需要复用,也可以直接在find的回调里写类型谓词,省去单独定义函数的步骤:
const numberValue = options?.find( (option): option is Extract<SelectOption, { text: 'b' }> => option.text === 'b' )?.value;
效果和方式一完全一致,numberValue类型为number | undefined。
完整修改后的代码
import "./styles.css"; type SelectOption = | { text: "a"; value: string; } | { text: "b"; value: number; }; type MultySelectOption = | { text: "c"; value: boolean; } | { text: "d"; value: Record<string, string>; }; type OptionsBy<T extends string> = T extends "select" ? SelectOption[] : T extends "multiSelect" ? MultySelectOption[] : never; // 可选:自定义类型守卫函数 function isSelectOptionWithText<T extends SelectOption['text']>( option: SelectOption, text: T ): option is Extract<SelectOption, { text: T }> { return option.text === text; } export default function App() { const options: OptionsBy<"select"> = []; // 选一种方式使用即可 const numberValue = options?.find(option => isSelectOptionWithText(option, 'b'))?.value; // const numberValue = options?.find( // (option): option is Extract<SelectOption, { text: 'b' }> => option.text === 'b' // )?.value; const sum = () => { return numberValue + 10; // 此处不再有类型报错 }; return <div className="App"></div>; }
内容的提问来源于stack exchange,提问作者whale
相关产品推荐
相关产品推荐

