【问题标题】:How do you declare the type a property of an object in-place, without needing to declare the type of the entire object?如何在不需要声明整个对象的类型的情况下将类型声明为对象的属性?
【发布时间】:2022-01-01 13:21:53
【问题描述】:

有没有办法在编写对象时键入对象的属性?与事先定义类型/接口相反。

我唯一能想到的就是as,但这太宽容了。考虑:

type Comment = Required<{
    author: string;
    message: string;
}>;

const myComment: Comment = {
    author: 'Steve',
    // Error! :) 'message' is missing
};

const myData = {
    myComment: {
        author: 'Steve',
        // No error. :(
    } as Comment,
};

const myData = {
    myComment: <Comment>{
        author: 'Steve',
        // No error. :(
    },
};

我想让myData.myComment 抛出同样的错误。

当然,这是一个简单的例子。但是,如果我正在编写一个大而复杂的对象,那么能够动态地为它的一部分声明类型会很好。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    匿名/内联界面会起作用吗?您仍然需要将它放在对象之前,但它比 interface/type 更简洁:

    const myData: { myComment: Comment } = {
      myComment: {
        author: 'Steve',
        // error
      },
    };
    

    【讨论】:

    • 我希望能够与相关财产一起进行。想象这是一个非常大的物体。但是,是的,我想这是我最好的选择。
    【解决方案2】:

    注意:Commentlib.dom.d.ts 中的内置类型。如果您将该标识符与 dom 库一起使用,您将收到以下错误:

    重复标识符“评论”。(2300)

    您可以使用恒等函数来确保输入可分配给参数类型:

    TS Playground

    type C = {
      author: string;
      message: string;
    };
    
    /** If you use this, you MUST provide the generic type argument to constrian your value */
    function id <T>(value: T): T {
      return value;
    }
    
    const number1 = id<number>('hello'); /*
                               ^^^^^^^
    Argument of type 'string' is not assignable to parameter of type 'number'.(2345)
    */
    
    // Don't forget to supply the generic type argument!
    const number2 = id('hello'); // typeof value2 === "hello"
    
    const myData1 = {
      myComment: id<C>({
        author: 'Steve',
        // message: 'Hi',
      }), /*
    ^^^^^^^^^^^^^^^^^^^^^^^^^
    Argument of type '{ author: string; }' is not assignable to parameter of type 'C'.
      Property 'message' is missing in type '{ author: string; }' but required in type 'C'.(2345) */
    };
    
    const myData2 = {
      myComment: id<C>({
        author: 'Alex',
        message: 'Hello',
      }), // ok
    };
    
    console.log(myData1); // { myComment: { author: 'Steve' } }
    console.log(myData2); // { myComment: { author: 'Alex', message: 'Hello' } }
    

    或者,如果您只是想避免打字,您可以在要包含它的对象之前定义注释,如下所示:

    TS Playground

    type C = {
      author: string;
      message: string;
    };
    
    let myComment: C = {
      author: 'Steve',
      message: 'Hi',
    };
    
    const myData1 = { myComment };
    
    myComment = {
      author: 'Alex',
      message: 'Hello',
    };
    
    const myData2 = { myComment };
    
    console.log(myData1); // { myComment: { author: 'Steve', message: 'Hi' } }
    console.log(myData2); // { myComment: { author: 'Alex', message: 'Hello' } }
    console.log(myComment); // { author: 'Alex', message: 'Hello' }
    

    【讨论】:

      【解决方案3】:

      一种选择是使用 IIFE,尽管它很难看并且对性能有(非常)小的影响:

      const myData = {
          myComment: ((): Comment => ({
              author: 'Steve',
              // Error! 'message' is missing
          }))(),
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-12
        • 1970-01-01
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 2012-02-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多