如何让TypeScript识别keyof泛型参数u为字符串类型?
解决TypeScript中
keyof类型兼容问题 问题根源是TypeScript中keyof T默认返回string | number | symbol类型(即便对象只有字符串键,数字也可作为合法键访问对象,因此keyof会包含number),导致u extends keyof t的类型范围超出了test方法所需的string类型。以下是几种优雅的解决方式:
方案1:直接约束泛型参数为字符串类型的键
修改generate方法的泛型约束,明确限定u是字符串类型且属于t的键:
interface MyDef { a: "a", } export class Router<t> { public generate<u extends string & keyof t>(path: u) { this.test(path); // 此时path会被TypeScript识别为string类型 } public test(s: string) { console.log(s); } } const x = new Router<MyDef>(); x.generate("a"); // 正常编译 x.generate("not-in-mydef"); // 编译报错,符合预期
方案2:约束类泛型并提取字符串类型键
若希望Router类仅处理字符串键的对象,可在类的泛型约束中做限制,同时用Extract提取keyof t中的字符串部分:
interface MyDef { a: "a", } export class Router<t extends Record<string, string>> { public generate<u extends Extract<keyof t, string>>(path: u) { this.test(path); } public test(s: string) { console.log(s); } } const x = new Router<MyDef>(); x.generate("a"); // 正常编译 x.generate("not-in-mydef"); // 编译报错,符合预期
方案3:精准类型断言(简洁且安全)
若能确定传入的键必然是字符串类型,可使用更精准的类型断言替代as any as string:
public generate<u extends keyof t>(path: u) { this.test(path as string); }
补充说明
你之前尝试的RouteSet或Record<string, string>约束无效,是因为即便t被约束为字符串索引对象,keyof t仍会包含number类型(JS中数字键会被自动转为字符串,TypeScript允许用数字访问字符串键的对象),导致u的类型范围仍不匹配string。
内容的提问来源于stack exchange,提问作者donatJ
相关产品推荐
相关产品推荐

