TypeScript中如何限制函数参数为非类实例及非Function类型
解决TypeScript限制函数参数禁止类实例和Function的问题
你的现有代码仅能排除Function类型,但类实例(比如new A())的类型不会匹配Function,因此无法触发编译错误。要同时禁止类实例和Function,可以通过以下两种方式实现:
方案1:精确排除类实例与Function
通过判断类型是否为Function,或是否为某个构造函数的实例(即类实例),来限制参数:
// 定义不允许的类型:Function 或 类实例(构造函数的实例) type Disallowed = Function | { constructor: new (...args: any[]) => any }; // 输入类型:仅允许非Disallowed的类型 type Input<T> = T extends Disallowed ? never : T; function saveData<T>(data: Input<T>) { // 函数逻辑 } // 测试用例 class A {} let foo = new A(); saveData(foo); // ❌ 编译错误:类实例被禁止 saveData(() => {}); // ❌ 编译错误:Function被禁止 saveData({ name: "test", age: 20 }); // ✅ 允许普通对象 saveData([1, 2, "hello"]); // ✅ 允许数组
注意:这个方案会排除所有类实例(包括内置类如Date、RegExp的实例),如果需要允许部分内置类实例,可以在Disallowed中针对性调整排除逻辑。
方案2:限制为JSON可序列化类型
如果你的函数需要处理的是可被JSON序列化的数据(如数字、字符串、普通对象、数组等),直接使用JSON可序列化类型更符合需求,同时自然排除了Function和类实例:
// 定义JSON可序列化类型(递归包含所有合法JSON类型) type JSONSerializable = | string | number | boolean | null | undefined | JSONSerializable[] | { [key: string]: JSONSerializable }; // 输入类型:仅允许JSON可序列化类型 type Input<T> = T extends JSONSerializable ? T : never; function saveData<T>(data: Input<T>) { // 函数逻辑 } // 测试用例 class A {} let foo = new A(); saveData(foo); // ❌ 编译错误:类实例不可序列化 saveData(() => {}); // ❌ 编译错误:Function不可序列化 saveData({ name: "test", tags: ["ts", "javascript"] }); // ✅ 允许 saveData(new Date()); // ❌ 编译错误:Date实例不可直接JSON序列化
这个方案更贴合“允许json object等合法数据”的需求,同时从根源上避免了传入会导致函数崩溃的类型。
内容的提问来源于stack exchange,提问作者TSR
相关产品推荐
相关产品推荐

