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

TypeScript箭头函数两种声明方式的差异及类型校验问题

TypeScript箭头函数声明的类型检查差异解析

问题重现

先看代码示例:

type MyState = {
  required: boolean;
  optional?: boolean;
};

const myFn1: (s: MyState) => MyState = (s) => ({...s, unexpected: 1})  // 无错误
const myFn2 = (s: MyState): MyState => ({...s, unexpected: 1})         // 报错

myFn2的错误信息:

Type '{ unexpected: number; required: boolean; optional?: boolean | undefined; }' is not assignable to type 'MyState'.
  Object literal may only specify known properties, and 'unexpected' does not exist in type 'MyState'.

两种写法的核心区别

myFn2报错原因

myFn2是直接给函数的返回值指定了MyState类型,返回的是对象字面量。TypeScript对直接赋值给类型的对象字面量会执行超额属性检查——只要字面量包含类型中未定义的属性,就会抛出错误,这是TS的一种保护机制,防止不小心添加多余属性。

myFn1不报错原因

myFn1是先给变量指定了完整的函数类型(s: MyState) => MyState,再把函数赋值给它。此时TS检查的是函数类型的兼容性:

  • 右侧函数的返回值类型是{ unexpected: number; required: boolean; optional?: boolean },这个类型是MyState的子类型(包含MyState的所有必填/可选属性)。
  • TS中函数的返回值是协变的,子类型可以安全赋值给父类型,因此不会触发超额属性检查,所以不会报错。

如何定义FnType让myFn3报错

要让const myFn3: FnType = (s) => ({...s, unexpected: 1})触发和myFn2一样的错误,需要让FnType的返回类型严格禁止额外属性,要求返回值精确匹配MyState。可以通过以下两种方式实现:

方法1:使用通用精确类型工具

// 定义通用的精确类型约束工具
type Exact<T> = T & Record<Exclude<keyof T, keyof T>, never>;

// 定义目标FnType
type FnType = (s: MyState) => Exact<MyState>;

方法2:直接添加额外属性禁止规则

type FnType = (s: MyState) => MyState & { [key: string]: never };

这种方式通过{ [key: string]: never }禁止任何额外的字符串属性,当返回对象包含unexpected这类多余属性时,number类型无法赋值给never类型,就会触发错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 06:16:18