TypeScript 系列:satisfies 的实用之处

假设我们要定义一份配置,如果直接写则没有类型提示,写错字段名或少写字段 TS 也不会报错。

ts 复制代码
const TIME_UNITS_TRANSLATIONS = {
    day: {
        singular: 'day',
        plural: 'days',
    },
    hour: {
        singular: 'hour',
        plural: 'hours',
    },
    minute: {
        singular: 'minute',
        plural: 'minutes',
    },
    second: {
        singular: 'second',
        plural: 'seconds',
    },
    millisecond: {
        singular: 'millisecond',
        plural: 'milliseconds',
    },
}

但若加上类型,确实解决了字段提示的问题,但是又会出现新问题:

ts 复制代码
type ITimeUnit = 'day' | 'hour' | 'minute' | 'second' | 'millisecond'
type IForms = {
    singular: string
    plural: string
}

const TIME_UNITS_TRANSLATIONS: Record<ITimeUnit, IForms> = {
    day: {
        singular: 'day',
        plural: 'days',
    },
    hour: {
        singular: 'hour',
        plural: 'hours',
    },
    minute: {
        singular: 'minute',
        plural: 'minutes',
    },
    second: {
        singular: 'second',
        plural: 'seconds',
    },
    millisecond: {
        singular: 'millisecond',
        plural: 'milliseconds',
    },
}

当我们 hover 变量其类型变成

const TIME_UNITS_TRANSLATIONS: Record<ITimeUnit, IForms>

而不加类型之前,VSCode 是能完整提示到字段级别的。这样便于我们观察变量,无需跳转到其定义处就能知道里面有哪些字段。

ts 复制代码
const TIME_UNITS_TRANSLATIONS: {  
    day: {  
        singular: string;  
        plural: string;  
    };  
    hour: {  
        singular: string;  
        plural: string;  
    };  
    minute: {  
        singular: string;  
        plural: string;  
    };  
    second: {  
        singular: string;  
        plural: string;  
    };  
    millisecond: {  
        singular: string;  
        plural: string;  
    };  
}

能否一举两得 - satisfies to the rescue 💉

ts 复制代码
const TIME_UNITS_TRANSLATIONS = {
    day: {
        singular: 'day',
        plural: 'days',
    },
    hour: {
        singular: 'hour',
        plural: 'hours',
    },
    minute: {
        singular: 'minute',
        plural: 'minutes',
    },
    second: {
        singular: 'second',
        plural: 'seconds',
    },
    millisecond: {
        singular: 'millisecond',
        plural: 'milliseconds',
    },
} satisfies Record<ITimeUnit, IForms>

这时候 hover 后发现我们平铺的类型定义又回来,而且字段能自动提示。

更进一步 - as const satisfies ... 🔬

能否做到更好?我们试试 as const satisfies ...

ts 复制代码
const TIME_UNITS_TRANSLATIONS = {
    day: {
        singular: 'day',
        plural: 'days',
    },
    hour: {
        singular: 'hour',
        plural: 'hours',
    },
    minute: {
        singular: 'minute',
        plural: 'minutes',
    },
    second: {
        singular: 'second',
        plural: 'seconds',
    },
    millisecond: {
        singular: 'millisecond',
        plural: 'milliseconds',
    },
} as const satisfies Record<ITimeUnit, IForms>

此时发现还能具体到字段的值,完美!

第二个例子

这个例子帮助我们更好理解 satisifies

ts 复制代码
type User = {
  id: string;
  name: string;
  age?: number;
};

const alice = {
  id: "123",
  name: "Alice",
  age: 30,
} satisfies User; // ✅ 类型仍然是 { id: string; name: string; age: number }

// 仍然可以访问 alice.age.toFixed(2),因为 age 被推断为 `number` 而不是 `number | undefined`

如果改成普通的类型标注:

ts 复制代码
const alice: User = {
  id: "123",
  name: "Alice",
  age: 30,
}; // 类型变成了 User 即 { id: string; name: string; age?: number }

alice.age.toFixed(2)
// ^^^^ 'alice.age' is possibly 'undefined'.(18048)

代码将报错因为 age 被推断为number | undefined 而不是 number

但实际上我们知道 alice 的 age 并不为空(30)。

到这里我们就学会了何时在项目中使用 satisifies 了 🎉!

总结

当我们想验证变量类型但不改变类型本身 ,可以试试 satisifies,打破鱼与熊掌二者不可兼得。

参考

相关推荐
路光.1 天前
React中Suspense的分包实践
前端·react.js·typescript
熊猫钓鱼>_>2 天前
仓颉语言:智能应用开发的新范式
ai·typescript·多模态·仓颉·cangjie·智能推荐系统·强类型
时间的情敌2 天前
基于 Vue3 及TypeScript 项目后的总结
前端·vue.js·typescript
Dragon Wu2 天前
Taro 自定义tab栏和自定义导航栏
前端·javascript·小程序·typescript·前端框架·taro
武清伯MVP3 天前
阮一峰《TypeScript 教程》学习笔记——类型映射
笔记·学习·typescript
Pu_Nine_93 天前
Vue 3 + TypeScript 项目性能优化全链路实战:从 2.1MB 到 130KB 的蜕变
前端·vue.js·性能优化·typescript·1024程序员节
快起来别睡了3 天前
TypeScript装饰器详解:像搭积木一样给代码加功能
前端·typescript
嗷呜~3 天前
error 找不到模块“../views/Login.vue”或其相应的类型声明
typescript·vue3
_光光3 天前
任务队列及大文件上传实现(前端篇)
前端·react.js·typescript
濮水大叔4 天前
VonaJS AOP编程🚀大杀器🔪:外部切面
typescript·node.js·nestjs