为啥类型 `Record<string,unknown>` 不接受具有已定义键的对象作为值
Posted
技术标签:
【中文标题】为啥类型 `Record<string,unknown>` 不接受具有已定义键的对象作为值【英文标题】:why type `Record<string,unknown>` does not accept object with defined keys as value为什么类型 `Record<string,unknown>` 不接受具有已定义键的对象作为值 【发布时间】:2021-10-13 02:02:24 【问题描述】:我正在尝试在类型中创建一个可以接受任何对象作为输入的函数。我把它定义为
type Props = onSubmit: (data: Record<string, unknown>) => void;
但是当我尝试将这种类型传递给它时
type SignIn = (data: email: string, password: string) => void;
我收到此错误
Type 'SignIn' is not assignable to type '(data: Record<string, unknown>) => void'.
Types of parameters 'data' and 'data' are incompatible.
Type 'Record<string, unknown>' is missing the following properties from type ' email: string; password: string; ': email, password
错误的完整示例是here
搞笑this works
【问题讨论】:
【参考方案1】:您的示例可以简化为:
declare var signin: (data: email: string, password: string ) => void
declare var record: (data: Record<string, unknown>) => void
signin = record
record = signin // error
如果您检查参数的可分配性,这会更有趣。你会看到可分配性被颠倒了。
declare var signinArg: email: string, password: string
declare var recordArg: Record<string, unknown>
signinArg = recordArg // error
recordArg = signinArg
为什么signin
不能分配给record
而signinArg
可以分配给recordArg
。
答案是: typescript 中的函数与它们的参数是相反的。这是设计使然。
有关 TypeScript 协方差的更多信息,您可以找到 here
尝试禁用strictFunctionTypes
编译器标志。你会看到错误消失了。
以前,所有函数都是双变量的,而且不安全。
Here您可以找到非常相似的问题,但问题的上下文更多
【讨论】:
谢谢你的详细解释,如果在 TS 文档中有这个就好了 我发现只有这个参考 typescriptlang.org/docs/handbook/release-notes/…【参考方案2】:不能将广义类型 (Record<string, unknown>
) 分配给特定类型 ( email: string, password: string
),反之亦然。
type SignIn = (data: Record<string, unknown>) => void;
const signIn: SignIn = ( email, password ) => console.log(email, password) ;
type Data = email: string, password: string
type Props =
onSubmit: (data: Data) => void
;
const onSubmit: Props = onSubmit: signIn ;
TypeScript playground
【讨论】:
【参考方案3】:这个问题也可以用这样的泛型来解决
type SignInData = email: string, password: string;
type SignIn = (data: SignInData) => void;
const signIn: SignIn = async (email, password) => console.log(email, password) ;
type Props<DATA extends Record<string, unknown>> = onSubmit: (data: DATA) => void;
const onSubmit: Props<SignInData> = onSubmit: signIn;
【讨论】:
以上是关于为啥类型 `Record<string,unknown>` 不接受具有已定义键的对象作为值的主要内容,如果未能解决你的问题,请参考以下文章
React Navigation + TypeScript 错误:类型“EventStackParams”不满足约束“Record<string, object |未定义>'
当类型是 Record <k,v> - NestJS 时,类验证器不起作用
我有一个 map<string, vector<record>>,如何从 vector<record> 中删除记录?