如何用TypeScript基于其他值创建动态类型?Angular组件场景
解决方案
要实现根据id和name的具体值动态推导items的类型,核心是让TypeScript能追踪到id和name的字面量类型,而非宽泛的string类型。以下是两种可行的实现方式:
方式一:泛型组件(推荐,类型更严谨)
通过泛型约束id和name的合法组合,确保两者取值始终匹配,同时自动推导items的类型:
import { Component, Input } from '@angular/core'; // 定义合法的id和name组合 type ValidFieldPairs = | { id: '_id'; name: 'name' } | { id: 'identifier'; name: 'title' }; // 根据组合生成对应的Item类型 type ItemFromPair<T extends ValidFieldPairs> = { [K in T['id'] | T['name']]: string; }; @Component({ selector: 'app-dynamic-item-list', template: `<!-- 组件模板 -->` }) export class DynamicItemListComponent<T extends ValidFieldPairs> { // 用泛型约束id和name的类型,默认值需做类型断言 @Input() id: T['id'] = '_id' as T['id']; @Input() name: T['name'] = 'name' as T['name']; // 自动推导items的类型 @Input() items: ItemFromPair<T>[] = []; }
使用组件时,TypeScript会根据传入的id和name自动推断items类型:
<!-- items类型为 {_id: string; name: string}[] --> <app-dynamic-item-list id="_id" name="name" [items]="[{_id: '1', name: '测试项'}]"> </app-dynamic-item-list> <!-- items类型为 {identifier: string; title: string}[] --> <app-dynamic-item-list id="identifier" name="title" [items]="[{identifier: '2', title: '新标题'}]"> </app-dynamic-item-list>
方式二:联合类型+条件类型
若不需要严格约束id和name的组合,可通过条件类型直接推导:
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-dynamic-item-list', template: `<!-- 组件模板 -->` }) export class DynamicItemListComponent { // 限定id和name的可选字面量值 @Input() id: '_id' | 'identifier' = '_id'; @Input() name: 'name' | 'title' = 'name'; // 通过条件类型推导items的类型 @Input() items: this['id'] extends '_id' ? {_id: string; name: string}[] : this['id'] extends 'identifier' ? {identifier: string; title: string}[] : never = []; }
原写法的问题分析
你之前的代码中,id和name的类型是宽泛的string,TypeScript无法追踪到它们的具体字面量值(如'_id'或'identifier'),因此this['id']和this['name']的类型均为string,最终Item<string, string>会生成{[key: string]: string}[],而非预期的带有具体键的对象数组。
内容的提问来源于stack exchange,提问作者Arthur Hlushko
相关产品推荐
相关产品推荐

