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

TypeScript中如何基于接口自动约束函数参数的键值类型?

Solution: Use Generics with keyof and Indexed Access Types

To achieve type-safe matching between settingName and settingValue without manually defining the union type, you can leverage TypeScript's generics, keyof operator, and indexed access types. Here's how to refactor your function:

interface Setting {
  names: string[]
  city: string | null
  age: number
}

function updateSetting<K extends keyof Setting>(settingName: K, settingValue: Setting[K]) {
  this.props.updateSetting({ [settingName]: settingValue })
}

How This Works:

  1. Generic Type Parameter K: The K extends keyof Setting constraint ensures settingName can only be one of the property names from the Setting interface ("names", "city", or "age").
  2. Indexed Access Type Setting[K]: This dynamically retrieves the type of the property in Setting that corresponds to the key K. So when you pass "names" as settingName, settingValue is enforced to be string[]; when you pass "city", it must be string | null, and so on.

Example Usage:

  • Valid calls (TypeScript will enforce correct types):
    updateSetting("names", ["Alice", "Bob"]); // ✅ Correct type for "names"
    updateSetting("city", null); // ✅ Correct type for "city"
    updateSetting("age", 30); // ✅ Correct type for "age"
    
  • Invalid calls (TypeScript will throw errors):
    updateSetting("city", 123); // ❌ Error: Type 'number' is not assignable to type 'string | null'
    updateSetting("invalidKey", "test"); // ❌ Error: Argument of type '"invalidKey"' is not assignable to parameter of type 'keyof Setting'
    

This approach keeps your code DRY (Don't Repeat Yourself) and automatically updates if you modify the Setting interface—no need to manually adjust the union type for settingValue anymore.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:53:40