You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript:根据另一属性值推断对应属性类型

TypeScript类型安全的订单属性更新方案

问题场景

现有如下TypeScript代码定义了订单、客户、地址相关接口,以及用于更新订单属性的请求接口:

interface Order {
    customer: Customer,
    address: Address
}

interface Customer {
    name: string
}

interface Address {
    firstLine: string
}

interface OrderUpdateRequest {
    key: 'customer'|'address',
    value: Customer | Address
}

const myThing = {customer: {name: 'Bob'}, address: {firstLine: 'my street'}} as Order

const updateRequest = {key:'customer',  value: {name : 'Dave'}} as OrderUpdateRequest
myThing[updateRequest['key']] = updateRequest['value']

执行上述代码时会出现以下类型错误:

Type 'Customer | Address' is not assignable to type 'Customer & Address'.
  Type 'Customer' is not assignable to type 'Customer & Address'.
    Property 'firstLine' is missing in type 'Customer' but required in type 'Address'.(2322)
input.tsx(11, 5): 'firstLine' is declared here.

错误原因

原OrderUpdateRequest接口中,key和value是独立的联合类型,TypeScript无法建立两者的关联关系。当执行赋值操作时,TS会假设updateRequest.key可能是customer或address中的任意一个,因此要求value必须同时兼容Customer和Address类型(即交叉类型Customer & Address),但实际传入的value只符合其中一种类型,导致类型不匹配。

解决方案

通过泛型接口将key和value的类型绑定,确保当key指定为Order的某个属性名时,value的类型自动匹配该属性对应的类型。

修改后的代码实现

interface Order {
    customer: Customer,
    address: Address
}

interface Customer {
    name: string
}

interface Address {
    firstLine: string
}

// 泛型请求接口,K约束为Order的键类型
interface OrderUpdateRequest<K extends keyof Order> {
    key: K,
    value: Order[K]
}

const myThing = {customer: {name: 'Bob'}, address: {firstLine: 'my street'}} as Order

// 泛型函数处理更新,确保类型安全
function updateOrder<K extends keyof Order>(order: Order, request: OrderUpdateRequest<K>) {
    order[request.key] = request.value
}

// 调用示例:key为'customer'时,value必须是Customer类型
updateOrder(myThing, {key: 'customer', value: {name: 'Dave'}})
// 调用示例:key为'address'时,value必须是Address类型
updateOrder(myThing, {key: 'address', value: {firstLine: 'new street'}})

直接使用泛型请求对象的写法

如果不需要封装函数,也可以直接通过泛型参数指定类型:

const customerUpdate: OrderUpdateRequest<'customer'> = {key: 'customer', value: {name: 'Dave'}}
myThing[customerUpdate.key] = customerUpdate.value

const addressUpdate: OrderUpdateRequest<'address'> = {key: 'address', value: {firstLine: 'new street'}}
myThing[addressUpdate.key] = addressUpdate.value

效果说明

修改后:

  • 当key为'customer'时,TypeScript会自动校验value必须符合Customer类型
  • 当key为'address'时,TypeScript会自动校验value必须符合Address类型
  • 若传入不匹配的key和value,会立即触发类型错误,实现类型安全的属性更新

内容的提问来源于stack exchange,提问作者Chris A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 11:35:59