TypeScript中如何从用户传入的动态数组推导动态类型?
TypeScript中如何从用户传入的动态数组推导动态类型?
嘿,这个场景我太熟悉了!const断言确实帮不上忙,因为它只能处理编译时就能确定的字面量值,而你这里的语言列表是用户在实例化类时动态传入的,属于模块本身编译时无法预知的输入。不过咱们可以用TypeScript的泛型来实现你想要的效果——让类的实例“记住”用户传入的具体语言类型,后续的highlight方法自动限制只能用这些语言。
直接上修改后的代码吧,先看HighLight.ts:
type Languages = "javascript" | "typescript" | "json" | "java" | "kotlin" | "python"; // 用泛型T捕获用户传入的具体语言类型,同时约束T必须是Languages的单个值或数组 export default class HighLight<T extends Languages | Languages[]> { private languages: T; constructor({ languages }: { languages: T }) { this.languages = languages; } // 通过条件类型判断:如果T是数组,就取数组的元素类型;如果是单个值,直接用T highlight(code: string, language: T extends Languages[] ? T[number] : T) { // 这里写你的高亮逻辑,比如根据language导入对应的高亮模块 console.log(`正在高亮${language}代码...`); } }
然后看用户侧的index.ts使用示例:
import HighLight from "./HighLight.ts"; // 传入数组,此时highlight的language参数只能是"javascript"或"typescript" const codeHighlighter = new HighLight({ languages: ["javascript", "typescript"] }); codeHighlighter.highlight("const x = 1;", "javascript"); // ✅ 类型正确 codeHighlighter.highlight("const x = 1;", "python"); // ❌ 类型错误,python不在传入的列表里 // 传入单个语言,highlight的language只能是"java" const javaHighlighter = new HighLight({ languages: "java" }); javaHighlighter.highlight("public class Test {}", "java"); // ✅ 类型正确 javaHighlighter.highlight("public class Test {}", "kotlin"); // ❌ 类型错误
原理其实很简单:泛型T会自动捕获用户传入的具体字面量类型——比如用户传入["javascript", "typescript"]时,T的类型就是readonly ["javascript", "typescript"]这种精确的字面量数组类型。然后highlight方法里的条件类型T extends Languages[] ? T[number] : T会自动判断用户传入的是单个语言还是数组,从而精准限制language参数的可选值。
如果用户是先定义一个数组变量再传入,比如:
const myLangs = ["javascript", "typescript"]; const highlighter = new HighLight({ languages: myLangs });
这时候TypeScript会把myLangs推导为string[],导致泛型T失去精确类型限制。这种情况可以让用户给数组加const断言:
const myLangs = ["javascript", "typescript"] as const; const highlighter = new HighLight({ languages: myLangs });
这样myLangs的类型就会被锁定为readonly ["javascript", "typescript"],泛型T也会捕获这个精确类型,highlight方法就能正常限制语言了。
备注:内容来源于stack exchange,提问作者Royal Foxy
相关产品推荐
相关产品推荐

