【问题标题】: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

【问题讨论】:

    标签: typescript


    【解决方案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 不能分配给recordsigninArg 可以分配给recordArg

    答案是: typescript 中的函数与它们的参数是相反的。这是设计使然。

    有关 TypeScript 协方差的更多信息,您可以找到 here

    尝试禁用strictFunctionTypes 编译器标志。你会看到错误消失了。

    以前,所有函数都是双变量的,而且不安全。

    Here您可以找到非常相似的问题,但问题的上下文更多

    【讨论】:

    【解决方案2】:

    不能将广义类型 (Record&lt;string, unknown&gt;) 分配给特定类型 ({ 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};
      

      【讨论】:

        猜你喜欢
        • 2021-04-24
        • 1970-01-01
        • 2022-06-11
        • 2015-05-29
        • 1970-01-01
        • 2021-03-13
        • 1970-01-01
        • 2016-08-23
        • 2021-03-16
        相关资源
        最近更新 更多