无需指定泛型参数,验证Element对象属性类型匹配及数组类型定义
解决方案:TypeScript 泛型元素数组的类型定义
针对你遇到的问题,核心需求是构建一个数组,其中每个元素都是合法的Element<T>(param与fn的类型严格匹配),同时支持任意未知的T类型,且不丢失类型检查。以下是两种可行方案:
方式1:泛型函数约束数组元素添加(推荐)
利用函数参数的逆变特性,通过泛型函数确保添加的元素合法,同时数组类型定义为Element<unknown>[](可兼容任意Element<T>):
type Element<T> = { param: T; fn: (a: T) => void; }; // 泛型函数:约束添加的元素必须是合法的Element<T> function addElement<T>(arr: Element<unknown>[], elem: Element<T>): void { arr.push(elem); } // 使用示例 const elements: Element<unknown>[] = []; // 合法元素:param与fn类型匹配 addElement(elements, { param: 1, fn: (a: number) => console.log(a) }); addElement(elements, { param: "foo", fn: (a: string) => console.log(a) }); // 非法元素:会被TypeScript拦截报错 addElement(elements, { param: 1, fn: (a: string) => console.log(a) });
遍历调用时完全安全,因为每个元素内部的param和fn类型在添加时已被约束匹配:
elements.forEach(elem => elem.fn(elem.param));
方式2:定义“任意合法Element”类型
通过条件类型直接定义数组元素的类型,确保每个元素内部的param与fn类型严格一致:
type Element<T> = { param: T; fn: (a: T) => void; }; // 定义任意合法的Element类型,自动约束param与fn的类型匹配 type AnyElement = Element<unknown> & { fn: (a: typeof this.param) => void; }; // 使用示例 const elements: AnyElement[] = [ { param: 1, fn: (a: number) => console.log(a) }, { param: true, fn: (a: boolean) => console.log(a) }, // 以下代码会报错:param类型number与fn期望的string不匹配 // { param: 1, fn: (a: string) => console.log(a) } ]; // 遍历调用同样安全 elements.forEach(elem => elem.fn(elem.param));
方案原理说明
两种方案都利用了TypeScript的函数参数逆变规则:(a: T) => void是(a: unknown) => void的子类型,因此任意Element<T>都可赋值给Element<unknown>。同时通过泛型函数或类型约束,确保每个元素内部的param与fn类型严格匹配,既支持任意未知T,又不会丢失类型检查。
内容的提问来源于stack exchange,提问作者Mat
相关产品推荐
相关产品推荐

