如何编写泛型以接收值必须为字符串的任意键接口?
问题描述
需要编写一个名为doThing的泛型函数,使用时需手动传入一个接口作为泛型参数。该接口可包含任意键,但所有值(包括可选值)必须为string类型;若接口中存在非string类型的值,TypeScript需抛出类型错误。示例代码如下:
function doThing<T extends ???>() { // do a thing } interface GoodInterface { foo: string bar?: string } interface BadInterface { foo: number bar: string } doThing<GoodInterface>() // 应正常运行 doThing<BadInterface>() // 应触发类型错误
最初尝试让泛型继承Record<string, string>,但出现错误:Index signature for type 'string' is missing in type 'GoodInterface'。不想为接口添加索引签名,请问该让泛型继承什么来实现此效果?
解决方案
可以使用映射类型作为泛型约束,替代Record<string, string>,这样无需为接口添加索引签名,同时确保所有属性值(包括可选属性)符合string类型要求(可选属性自动兼容undefined)。
修改后的函数定义如下:
function doThing<T extends { [K in keyof T]: string | undefined }>() { // do a thing }
原理说明
{ [K in keyof T]: string | undefined }是映射类型,它会遍历泛型参数T的所有属性键K,要求每个键对应的属性类型必须是string或undefined——这正好匹配可选属性的本质(string | undefined)。- 与
Record<string, string>不同,这个映射类型不需要目标接口拥有全局字符串索引签名,仅针对接口自身定义的属性做约束,完美适配显式定义属性的接口。
验证效果
doThing<GoodInterface>():GoodInterface的foo是string,bar是string | undefined,符合约束,正常运行。doThing<BadInterface>():BadInterface的foo是number,不满足string | undefined的类型要求,TypeScript会抛出类型错误。
如果希望更严格地排除undefined(仅允许必填的string属性,可选属性也必须为纯string),可以调整约束为:
function doThing<T extends { [K in keyof T]: string }>() { // do a thing }
此时GoodInterface的可选属性bar?: string会因为包含undefined触发错误,可根据实际需求选择。
内容的提问来源于stack exchange,提问作者Blargel
相关产品推荐
相关产品推荐

