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

如何让TypeScript函数自动推断传入类实例的泛型类型?

泛型函数requireParams的类型自动推断实现方案

需求背景

需要构建泛型函数requireParams,用于确保类初始化时特定属性已被设置(动态数据场景下无法通过必填参数直接约束),希望函数能自动从传入的类实例参数推断泛型类型,无需手动指定。

当前实现代码

export const requireParams = (cls: AnyClass, requiredParams: string[]) => {
  if (!requiredParams) {
    return;
  }

  const missingParams = requiredParams.filter(
    (param) => cls?.[param] === undefined || cls?.[param] === null || cls?.[param] === NaN
  );
  if (missingParams.length) {
    throw new Error(`Missing required params: ${missingParams.join(", ")}`);
  }
};

使用示例

class Foo {
  constructor(public readonly food: string) {
    requireParams(this, ['food']);
  }
}

尝试过的无效类型定义

type AnyClass<T> = T extends new (...args: any[]) => infer R ? R : never;

该定义试图从构造函数推断实例类型,但因函数实际接收的是类实例而非构造函数,导致泛型参数T始终返回never。

解决方案

核心问题是之前的类型推断方向错误:函数接收的是类实例而非构造函数,因此需要基于实例类型做泛型约束,而非构造函数。修改后的实现如下:

export const requireParams = <T extends object>(obj: T, requiredParams: Array<keyof T>) => {
  if (!requiredParams.length) {
    return;
  }

  const missingParams = requiredParams.filter(
    (param) => obj[param] === undefined || obj[param] === null || Number.isNaN(obj[param])
  );
  if (missingParams.length) {
    throw new Error(`Missing required params: ${missingParams.join(", ")}`);
  }
};

关键优化点

  1. 泛型约束自动推断:<T extends object>会自动从传入的obj(即类实例this)推断出具体的实例类型,无需手动指定
  2. 参数类型校验:Array<keyof T>限制必填参数必须是实例T的属性键,避免传入不存在的属性名,同时提供类型提示
  3. 修正NaN判断:原代码中cls?.[param] === NaN永远为false(NaN不等于任何值),替换为Number.isNaN()实现正确判断

优化后使用效果

class Foo {
  constructor(public readonly food: string) {
    requireParams(this, ['food']); // 类型匹配,无报错
    // requireParams(this, ['nonExistent']); // TS直接报错:属性"nonExistent"不存在于类型"Foo"
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:10:33