Angular泛型组件中T[K]类型如何适配string|number入参要求
问题解决:Angular泛型组件属性类型不匹配报错
问题根源
你当前的泛型约束只限制了key是obj的字符串类型属性键,但没有限制该属性的值必须符合currency函数要求的string | number类型,因此TS无法确认obj[key]的类型合法性,抛出类型错误。
合规解决方案
方案1:增加泛型约束,从传入阶段保证类型合法(最优解)
直接在泛型定义层面对属性值类型做限制,从组件调用的源头就拦截不合法入参,完全保证类型安全,适配Angular模板严格类型检查规则:
// 新增泛型约束:要求T的K属性必须为string | number类型 class TextComponent<T extends Record<K, string | number>, K extends Extract<keyof T, string>> { @Input() obj : T; @Input() key: K; constructor(){} // 说明:函数签名保持不变 currency(cost: string | number) { console.log('func::currency', cost); } test(){ // 不再报错,TS已确认T[K]符合入参类型要求 this.currency(this.obj[this.key]); } }
该方案下如果传入的obj和key对应的属性不是string|number类型,TS会在组件传参阶段就抛出错误,提前发现问题,同时模板中使用currency管道也不会再报类型错误。
方案2:类型收窄,运行时判断类型
如果你的组件需要支持key对应其他类型的属性,仅在调用currency的时候做特殊处理,可以用类型守卫做运行时类型收窄,不需要as any强转:
class TextComponent<T, K extends Extract<keyof T, string>> { @Input() obj : T; @Input() key: K; constructor(){} // 说明:函数签名保持不变 currency(cost: string | number) { console.log('func::currency', cost); } // 自定义类型守卫,判断值是否符合currency入参要求 private isStringOrNumber(val: unknown): val is string | number { return typeof val === 'string' || typeof val === 'number' } test(){ const value = this.obj[this.key] if(this.isStringOrNumber(value)) { // 进入该分支时TS已确认value类型为string|number,可直接传入 this.currency(value) } else { // 可自定义不合法类型的兜底逻辑,比如传默认值/打印错误日志 console.warn(`属性${String(this.key)}的值类型不符合currency要求,使用默认值0`) this.currency(0) } } }
该方案灵活性更高,不需要限制组件的泛型范围,兼容更多使用场景,同时保证类型安全。
内容的提问来源于stack exchange,提问作者ethiers
相关产品推荐
相关产品推荐

