【问题标题】:Difference between Record<key, type> and [key: string]: typeRecord<key, type> 和 [key: string] 的区别:类型
【发布时间】:2021-04-20 05:03:12
【问题描述】:

我想知道Record&lt;key, type&gt;[key: string]: type 之间的区别。我们可以互换使用它们吗?哪个更动态和类型安全?

我有一个例子,我可以互换使用它们。哪个是好的做法?

//Record example
interface PageInfo {
  title: string;
}

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};

console.log(nav.about);
// object example

type Page2 = {
  [key: string]: PageInfo;
};

const navHtml: Page2 = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};

console.log(navHtml.contact);

Typescript playground for this example

【问题讨论】:

    标签: typescript typescript-utility


    【解决方案1】:

    首先,AFAIK,它们都不是完全类型安全的。

    this issue

    您可以在 Record - Record&lt;Page, PageInfo&gt; 中将联合类型用作 key,而在索引类型中则不能:

    type Page2 = {
      [key: string | number | symbol]: PageInfo; // error
    };
    

    例子

    //Record example
    interface PageInfo {
      title: string;
    }
    
    type Page = "home" | "about" | "contact";
    
    const nav: Record<Page, PageInfo> = {
      about: { title: "about" },
      contact: { title: "contact" },
      home: { title: "home" },
    };
    
    console.log(nav.about);
    // object example
    
    type Page2 = {
      [key: string]: PageInfo;
    };
    
    const navHtml: Page2 = {
      about: { title: "about" },
      contact: { title: "contact" },
      home: { title: "home" },
    };
    
    console.log(navHtml.contact);
    
    /**
     * If you have a string as a key - no problem
     */
    type Test1 = Record<string, string> extends { [p: string]: string } ? true : false // true
    type Test2 = { [p: string]: string } extends Record<string, string> ? true : false // true
    
    const foo = (arg: Record<string, string>) => arg
    const indexed: { [p: string]: string } = { bar: 'bar' }
    foo(indexed) // no error
    
    /**
     * And vice-versa
     */
    const bar = (arg: { [p: string]: string }) => arg
    const record: Record<string, string> = { bar: 'bar' }
    foo(record) // no error
    
    /**
     * But if you have a union type as a key
     * Above approach will not work
     */
    type Test3 = Record<'a' | 'b', string> extends { [p: string]: string } ? true : false // true
    type Test4 = { [p: string]: string } extends Record<'a' | 'b', string> ? true : false // false
    
    const withIndex: Record<'a' | 'b', string> = { bar: 'bar' } // missing a,b
    

    更新

    /**
     * Explanation of Record<'a'|'b', string>
     * It is mean that objects should have a & b keys
     */
    
    type CustomRecord = Record<'a' | 'b', string>
    
    const allowedRecord: CustomRecord = {
      a: '1',
      b: '2'
    } // ok
    
    const allowedRecord2: CustomRecord = {
      a: '1',
    } // error, because without b
    
    const allowedRecord3: CustomRecord = {
      b: '1',
    } // error, because without a
    
    /**
     * You are unable to do same thing with indexed type
     */
    type TypeIndexedWIthExplicitKeys = {
      [p: string | number]: string
    }
    
    interface InterfaceIndexedWIthExplicitKeys {
      [p: 'a' | 'b']: string
    }
    
    const x: InterfaceIndexedWIthExplicitKeys = { 2: 's' } // no error, but.... I would expect an error
    const y: TypeIndexedWIthExplicitKeys = { 2: 's' } // no error, but.... I would expect an error
    
    
    const check = (): InterfaceIndexedWIthExplicitKeys => {
      return { 2: 2 } // no error, but I would expect
    }
    type MyRecord = Record<'a' | 'b', string>
    
    const z: MyRecord = { 2: '2' } // error, because we expect a & b
    const c: MyRecord = { a: '2', b: '3' } // ok
    

    【讨论】:

    • 我对Test3和Test4有点困惑。你能提供一个或多个例子来解释同一件事吗?这对我很有帮助
    • 啊...理解“您可以将联合类型用作 Record - Record 中的键,而您不能在索引类型中使用:”您通过示例解释了同样的事情.
    猜你喜欢
    • 2021-04-10
    • 2011-04-20
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 2013-12-02
    • 2019-02-13
    • 1970-01-01
    相关资源
    最近更新 更多