TypeScript从键列表推断对象属性:CSV阅读器类型优化问题
解决TypeScript中CSV阅读器的类型约束问题
原代码的问题在于CsvHeaders被定义为readonly string[],这是一个宽泛的通用类型,TypeScript无法从中提取出具体的字符串字面量(比如'A'、'B'、'C'),所以CsvHeaders[number]会被推断为string,最终CsvRow就变成了{ [x: string]: string }——也就是任意字符串键都合法的对象,自然访问row.Anything不会触发类型错误。
要实现你想要的类型约束,核心是通过泛型保留headers的具体字面量类型信息,修改方案如下:
// 用泛型H捕获headers的具体字面量类型 interface ICsvReaderProps<H extends readonly string[]> { headers: H; // row的键被严格约束为H中的具体字符串字面量 onRowClick: (row: Record<H[number], string>) => void; } // 自动推断泛型参数,无需手动指定 const a = { headers: ['A', 'B', 'C'] as const, onRowClick: (row) => console.log(row.Anything), // 此处会抛出类型错误:类型“{ A: string; B: string; C: string; }”上不存在属性“Anything” } satisfies ICsvReaderProps<readonly ['A', 'B', 'C']>;
如果希望写法更简洁,也可以用工厂函数封装,让TypeScript自动完成类型推断:
function createCsvReader<H extends readonly string[]>(props: ICsvReaderProps<H>) { return props; } const b = createCsvReader({ headers: ['A', 'B', 'C'] as const, onRowClick: (row) => { console.log(row.A); // 合法,符合预期 console.log(row.Anything); // 类型错误,符合预期 } });
这种修改的关键是把原本宽泛的CsvHeaders类型替换为泛型参数H,让TypeScript能捕获到headers数组里的具体字符串字面量,进而严格约束onRowClick参数的键只能是headers中存在的字段。
内容的提问来源于stack exchange,提问作者Velocirooster
相关产品推荐
相关产品推荐

