typescript - TypeScript 功能解构不强制执行默认类型
问题描述
我有一个接受单个对象参数的函数,如下所示。(注意,这是一个人为的例子,但它说明了问题。)
type FuncParams = { sayYes: boolean; }
type FuncType = (params: FuncParams) => string;
const maybeSayYes: FuncType = ({ sayYes }) => sayYes ? 'Yes' : 'No';
maybeSayYes({ sayYes: true }); // Returns 'Yes'
maybeSayYes({ sayYes: false }); // Returns 'No'
我想让这个sayYes
属性成为可选的,所以我更新了如下类型并在函数声明中添加了一个默认值:
type FuncParams = { sayYes?: boolean; }
type FuncType = (params: FuncParams) => string;
const maybeSayYes: FuncType = ({ sayYes = true }) => sayYes ? 'Yes' : 'No';
maybeSayYes({ sayYes: true }); // Returns 'Yes'
maybeSayYes({ sayYes: false }); // Returns 'No'
maybeSayYes({}); // Returns 'Yes'
但是,我注意到我可以分配任何默认值,sayYes
并且 TypeScript 不会标记不正确的类型。例如:
const maybeSayYes: FuncType = ({ sayYes = 'notABoolean' }) => sayYes ? 'Yes' : 'No';
我希望 TypeScript 能够从中推断boolean
类型FuncType
并阻止我分配 a string
,但事实并非如此。
如果我按如下方式显式键入参数,则可以显示错误:
const maybeSayYes: FuncType = ({ sayYes = 'notABoolean' }: FuncParams) => sayYes ? 'Yes' : 'No';
但是,我假设 TypeScript 会从FuncType
. 我确定这是我对 TypeScript 的理解有问题,但我想知道:
- 为什么 TypeScript 没有告诉我这
'notABoolean'
不是boolean
. - 如何在不必重复
FuncParams
输入的情况下约束默认值类型。
解决方案
我对您描述的行为感到惊讶,但我对 TypeScript 的了解仍然不是很深。
您可以使用函数重载类型来做到这一点:
type FuncParams = { sayYes?: boolean; }
type FuncType = {
(params: FuncParams): string;
(params: FuncParams & {sayYes: never}): string; // Or just: {params: {sayYes: never}: any;
};
然后,尝试使用sayYes
非boolean
类型的调用将匹配第二个重载并导致错误。(非常感谢jcalz指出它sayYes
仍然是可选的,并且您可以使用更简单的签名来处理never
重载。)
这给了你这种行为:
// Correct default value type
const maybeSayYes1: FuncType = ({ sayYes = true }) => sayYes ? 'Yes' : 'No';
// Incorrect default value type
const maybeSayYes2: FuncType = ({ sayYes = 'notABoolean' }) => sayYes ? 'Yes' : 'No';
// ^−−−−−−−−−−−−− TypeScript compiler error here
// Correctly don't have it at all (since it's optional)
const maybeSayYes3: FuncType = ({ }) => Math.random() ? 'Yes' : 'No';
推荐阅读
- git - git clone 排除 lfs 文件
- ansible - 如何在 ansible 中运行 AWS 命令
- c++ - 使用 dart:ffi 实现 winapi(SendInput)
- m2doc - 兼容 capella 1.4.0 的 M2DOC 版本何时可用?
- sql - 将 Sql Schema 转换为 JDL 格式
- javascript - 在更改视图网格 fullcalendar v4 上拖放后,带有 rrule 插件的事件未更新
- c# - 在 asp.net 核心中使用返回 url 和 cookie 身份验证
- excel - 我可以使用 Python 自动更改 Excel 插件中的提示吗?
- java - Java, Inheritance, Generics - using parameters of subtypes in template method implementations
- python - 如何在另一个脚本中运行一个脚本?