TypeScript:如何从抽象类的字符串数组生成联合类型?
问题解决:基于抽象类的只读字符串数组生成联合类型参数
问题分析
你遇到两个核心问题:
- 错误提示
'U' only refers to a type, but is being used as a value here.:泛型参数U是类型层面的标识,不能直接用于typeof操作符(typeof仅能作用于运行时值)。 column()方法参数无限制:MyTable的fields被TypeScript自动拓宽为readonly string[],丢失了具体的字面量类型信息,导致参数无法被约束。
解决方案
步骤1:保留fields的字面量类型
修改MyTable的fields定义,用as const断言让TypeScript保留数组元素的字面量类型,避免被自动拓宽为string[]:
export class MyTable extends Table { fields = ['a', 'b', 'c'] as const; // 用as const锁定字面量类型 }
也可以显式指定类型来达到同样效果:
export class MyTable extends Table { fields: readonly ['a', 'b', 'c'] = ['a', 'b', 'c']; }
步骤2:修正column()方法的参数类型
不能直接用泛型U取类型,而是从实例的table属性(运行时存在的值)提取类型,或者在泛型中明确捕获字段元素类型:
方案A:从实例属性提取类型
直接在column方法中使用typeof this.table.fields[number],利用this.table的运行时值推导类型:
export class ResultSet<T, U extends Table> { protected readonly _rows: T[] | T; constructor(rows: T[] | T, readonly table: U) { this._rows = rows; } column(name: typeof this.table.fields[number]) {} }
方案B:泛型中明确提取字段类型
通过额外泛型参数直接捕获fields的元素类型,让约束逻辑更清晰:
// 泛型F表示fields的元素联合类型 export class ResultSet<T, F extends string, U extends Table & { fields: readonly F[] }> { protected readonly _rows: T[] | T; constructor(rows: T[] | T, readonly table: U) { this._rows = rows; } column(name: F) {} }
完整可运行代码
export abstract class Table { abstract fields: readonly string[]; } export class MyTable extends Table { fields = ['a', 'b', 'c'] as const; } export class ResultSet<T, U extends Table> { protected readonly _rows: T[] | T; constructor(rows: T[] | T, readonly table: U) { this._rows = rows; } column(name: typeof this.table.fields[number]) {} } const set = new ResultSet([], new MyTable()); set.column('123'); // 此处触发类型错误,符合预期 set.column('a'); // 正常通过类型检查
效果验证
现在column()方法的参数会被严格约束为'a' | 'b' | 'c',传入非指定字符串会直接触发TypeScript类型错误,完全符合需求。
内容的提问来源于stack exchange,提问作者Get Off My Lawn
相关产品推荐
相关产品推荐

