TypeScript中如何修剪类实例的所有字符串属性?
遍历类实例字符串属性并调用trim()的TypeScript解决办法
问题场景
有这么个Person类:
class Person { name?: string | null; age?: number | null; friends!: Person[]; isLucky: boolean; }
想遍历它的实例,给所有字符串属性调用trim(),写了这段代码却触发TypeScript类型错误:
(Object.keys(person) as (keyof typeof person)[]).forEach((key) => { const value = person[key]; if (typeof value === 'string') { person[key] = value.trim(); // 报错:Type 'string' is not assignable to type 'person[keyof person]' } });
需要写一个通用方法,能适配不同类的实例,搞定类型问题。
报错原因
TypeScript没法在forEach回调里精准判断person[key]的具体类型——key是keyof Person的联合类型,person[key]对应的是所有属性类型的集合(比如string|null|number|boolean|Person[]),而value.trim()返回的纯string没法直接赋值给这个混合类型。
解决方案
1. 针对单个类的快速修复
如果只处理Person实例,直接给key加个类型断言,告诉TS当前键对应的是字符串属性:
(Object.keys(person) as (keyof Person)[]).forEach((key) => { const value = person[key]; if (typeof value === 'string') { // 断言key对应的属性是string类型 person[key as keyof Person & { [K in keyof Person]: Person[K] extends string ? K : never }] = value.trim(); } });
2. 通用方法(推荐)
要适配任意类的实例,用泛型+条件类型写个通用函数,自动筛选字符串属性:
// 定义类型:筛选出对象T中属性为string/string|null/undefined的键 type StringKeys<T> = { [K in keyof T]: T[K] extends string | null | undefined ? K : never; }[keyof T]; // 通用trim方法,处理任意对象的字符串属性 function trimStringProperties<T>(obj: T): void { (Object.keys(obj) as StringKeys<T>[]).forEach((key) => { const value = obj[key]; // 只处理非null/undefined的字符串 if (typeof value === 'string') { obj[key] = value.trim() as T[StringKeys<T>]; } }); } // 用例 const person = new Person(); person.name = " Bob "; trimStringProperties(person); console.log(person.name); // 输出"Bob"
3. 更严格的版本(可选)
如果只想处理纯string类型(排除null/undefined),调整条件类型即可:
type StrictStringKeys<T> = { [K in keyof T]: Exclude<T[K], null | undefined> extends string ? K : never; }[keyof T]; function trimStrictStringProperties<T>(obj: T): void { (Object.keys(obj) as StrictStringKeys<T>[]).forEach((key) => { const value = obj[key]; if (typeof value === 'string') { obj[key] = value.trim() as T[StrictStringKeys<T>]; } }); }
关键类型技巧
- 条件类型
StringKeys<T>:遍历对象的所有键,只保留属性类型包含string的键,自动过滤数字、布尔等非字符串属性。 - 类型断言:赋值时用
as T[StringKeys<T>]让TS确认赋值类型和目标属性类型匹配。 - 泛型:让方法支持任意类型的实例,不用为每个类单独写逻辑。
内容的提问来源于stack exchange,提问作者agt-ru
相关产品推荐
相关产品推荐

