TypeScript如何提取类型中指定值类型对应的属性键
实现方案
核心是通过映射类型遍历泛型T的所有属性,筛选出值类型符合要求的属性键,再组合为数组类型即可。
核心类型定义
// 通用工具类型:提取类型T中所有值类型匹配V的属性键 type KeysOfType<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T]; // 提取值为number的属性键数组类型 type KeysOfNumbers<T> = Array<KeysOfType<T, number>>; // 提取值为boolean的属性键数组类型 type KeysOfBooleans<T> = Array<KeysOfType<T, boolean>>;
注意事项
- 原代码存在字段大小写不匹配问题:CSV表头为
IsRead、IsAD,但Mail类型中定义为小写开头的isRead、isAD,运行时会因字段名不一致导致布尔转换失效,需要统一两边命名。 - TypeScript 对
Array.includes的参数有严格类型校验,context.column.toString()返回通用string类型,会和字面量类型的属性键产生类型冲突,只需在调用includes时做简单类型断言即可,不影响运行逻辑。
完整修正代码
import {CastingFunction, parse} from 'csv-parse/browser/esm/sync'; const input = 'ID,Type,From,Title,Content,Date,IsRead,IsAD\r\n1,0,Mars,My car glass was broken,How much DOGE to fix this.....,423042301654134900000,false,false'; // 字段名和CSV表头对齐 type Mail = { ID: string; Type: number; From: string; Title: string; Content: string; Date: number; IsRead: boolean; IsAD: boolean; }; type KeysOfType<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T]; type KeysOfNumbers<T> = Array<KeysOfType<T, number>>; type KeysOfBooleans<T> = Array<KeysOfType<T, boolean>>; const castNumberAndBoolean = <T>( keysOfNumbers: KeysOfNumbers<T>, keysOfBooleans: KeysOfBooleans<T>, ): CastingFunction => (value, context) => { const column = context.column.toString(); if (keysOfNumbers.includes(column as KeysOfType<T, number>)) { return Number(value); } if (keysOfBooleans.includes(column as KeysOfType<T, boolean>)) { return value === 'true'; } return value; }; parse(input, { columns: true, cast: castNumberAndBoolean<Mail>(['Type', 'Date'], ['IsRead', 'IsAD']), });
修改完成后,TypeScript 会自动校验传入的字段名是否合法:如果将非number类型的字段(如类型为string的ID)传入第一个参数,或是将非boolean类型的字段传入第二个参数,编译器会直接抛出类型错误,从根源上避免传参错误。
内容的提问来源于stack exchange,提问作者張政鈞
相关产品推荐
相关产品推荐

