如何在TypeScript中处理对象并添加新的字段?

现有一个a对象和b对象,a对象为服务器返回的数据,b对象为对a对象加工后的数据。

类型为:

interface C {
  a: string
  b: string
  c: string
}

type A = Omit<C, 'c'>

type B = C

由于A数据并没有c字段, 我要加c字段,但是加c字段又提示A没有c字段,如:

a.c = 'abc' // 报错类型A上不存在属性c
b = a

还是说我直接把类型定义为:

interface C {
  a: string
  b: string
  c?: string
}

type A = C

type B = C
阅读 1.2k
2 个回答

一个方式就是问题中所展示的, 但是不太灵活, 可以使用接口的任意属性:

interface Person {
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

使用 [propName: string] 定义了任意属性取 string 类型的值。

需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集:

interface Person {
    name: string;
    age?: number;
    [propName: string]: string;
}

let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};

// index.ts(3,5): error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
// index.ts(7,5): error TS2322: Type '{ [x: string]: string | number; name: string; age: number; gender: string; }' is not assignable to type 'Person'.
//   Index signatures are incompatible.
//     Type 'string | number' is not assignable to type 'string'.
//       Type 'number' is not assignable to type 'string'.
http://ts.xcatliu.com/basics/type-of-object-interfaces.html

假如服务端响应的数据类型如下:

interface User {
    id: number
    username: string
}

现在前端需要为每个User添加一个默认头像,则前端实际使用的数据类型如下:

interface User {
    id: number
    username: string
    avatar: string
}

你的问题是,想在响应的数据中添加avatar属性,这在 typescript 中是不可能的,编译不通过。

解决这个问题的前提是需要知道 typescript 本质上仍然是 javascript,你在 javascript 中可以很随意地为一个对象添加属性,即便它在定义或初始化时并不存在这个属性。那换个角度想一下,如果你在 javascript 中获取一个对象上不存在的属性时会是什么结果?

let o = {id: 1, username: "user"}

console.log(o.avatar) // undefined

undefined

这就是 typescript 的接口中属性的?的用途。

interface User {
    id: number
    username: string
    avatar?: string
}

?即代表avatar可能存在,也可能不存在,这样的话,你就可以给avatar赋值了:

const response: User = {id: 1, username: 'user'}
response.avatar = 'https://example.com/avatar.png'

// 如果你不给 avatar 赋值,则 response.avatar 也是 undefined,这一点与 javascript 是一致的。

到这里基本上就已经解决了你的问题,但是,如果你希望在使用时不希望编辑器老是提示avatar可能是undefined,那就是另一个问题了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
Microsoft
子站问答
访问
宣传栏