打字稿中带有泛型的可选类型

时间:2020-09-09 05:07:46

标签: typescript generics

[我想]


interface T {
    a?: string;
    b?: number;
    c?: boolean;
    d?: object;
    e?: null;
}

type A = {
    a: string;
    b: number;
    q: string; // not exist in type T
}


type B = {
    a: string;
    b: number;
}

type G<U extends T> = {
  data: U;
  creator: () => void;
}

const someFunc = <U>(data: U): G<U> => {
  return {
      data,
      creator: () => { console.log(data ) }
  }
}

const funcA = (data: A) => {
    const something = someFunc<A>(data); // I want to occur error
}

const funcB = (data: B) => {
    const something = someFunc<B>(data); // I want to do well
}

类型'T'具有可选属性(每个属性)。

一种类型是类型“ T”(是“ B”)的子集

另一个不是“ T”类型的子集(是“ A”-具有属性“ q”)

但是,使用“ B”类型不会发生错误。

怎么办?

谢谢。

2 个答案:

答案 0 :(得分:2)

没有错误的原因是我们所说的"msg": "error running gluster (/usr/sbin/gluster --mode=script volume add-brick var-www replica 2 server01-private:/server01-private:/data/glusterfs/var-www/brick01/brick server01-private:/server02-private:/data/glusterfs/var-www/brick02/brick server02-private:/server01-private:/data/glusterfs/var-www/brick01/brick server02-private:/server02-private:/data/glusterfs/var-www/brick02/brick force) command (rc=1): internet address 'server01-private:/server01-private' does not conform to standards\ninternet address 'server01-private:/server02-private' does not conform to standards\ninternet address 'server02-private:/server01-private' does not conform to standards\ninternet address 'server02-private:/server02-private' does not conform to standards\nvolume add-brick: failed: Host server01-private:/server01-private is not in 'Peer in Cluster' state\n" 的意思,这意味着-“我接受所有具有T的所有属性的U”。我们的T是非常松散的类型,每个属性都是可选的,然后只包含这些属性的一部分的类型完全可以,因为原始T从未说过字段是强制性的。让我们进行类型级别检查以证明我的话:

U extends T

您可以问-为什么A是否有其他字段。是的,它具有但也满足T的所有要求,这个附加字段不会破坏T的所有属性都在A中的事实。同样从实际的思维方式来看,如果我们使用属性让我们说a和b,那么如果对象具有q,这不是问题,因为我们不使用此属性,所以不会发生任何不良情况。

仅供参考。在键迭代之外,禁止附加属性没有实际的意义。但是,如果您对此感兴趣,这里是完整的解决方案-Advanced TypeScript Exercises - Answer 7

答案 1 :(得分:2)

如果对象存储在变量中,FYI Typescript允许过多的属性:

解决这些检查的最后一种方法,可能有点 令人惊讶的是将对象分配给另一个变量: squareOptions不会进行过多的属性检查,编译器不会 给你一个错误。 https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks

因此,即使您的函数期望使用T,它也会起作用:

interface T {
  a?: string;
  b?: number;
  c?: boolean;
  d?: object;
  e?: null;
}

interface A {
  a: string;
  b: number;
  q: string; // not exist in type T
}

const foo: A = {
  a: "a",
  b: 1,
  q: "q",
};

const someFunc = (data: T) => console.log(data);

someFunc(foo);

在您的示例中,它“更有效”,因为您期望扩展T(在此行type G<U extends T> = {中),这意味着任何尊重接口T的事物而A确实如此。

其他说明:您的函数someFunc对类型U没有限制,因此它将接受任何内容:

const funcC = (data: number) => {
    const something = someFunc<number>(data); // Also valid
}

要最终回答您的问题并能够禁止使用其他属性,请在此处提供详细的答案:https://stackoverflow.com/a/57117594/3292234