简体   繁体   English

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

[英]optional type with generic in typescript

[I want to] [我想要]


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
}

Type 'T' has optional property ( every property ).类型“T”具有可选属性(每个属性)。

One type is subset of type "T" ( is "B" )一种类型是“T”类型的子集(是“B”)

Another one is not subset of type "T" ( is "A" - has property "q" )另一个不是“T”类型的子集(是“A” - 具有属性“q”)

But, using type "B" is not occured error.但是,使用类型“B”不会发生错误。

How to do?怎么做?

Thank you.谢谢你。

The reason of no error is what we mean by U extends T , and this means - "I accept any U which has all properties of T".没有错误的原因是我们所说的U extends T ,这意味着 - “我接受任何具有 T 的所有属性的 U”。 Our T is very loose type, every property is optional, then types with only part of these properties are fully ok, as the original T never said that fields are mandatory.我们的 T 是非常松散的类型,每个属性都是可选的,那么只有这些属性的一部分的类型是完全可以的,因为原始 T 从未说过字段是必需的。 Lets do the type level check to prove my words:让我们做类型级别检查来证明我的话:

type AextendsT = A extends T ? true : false; // true
type BextendsT = B extends T ? true : false; // true

You can ask - why if A has additional field.你可以问 - 为什么如果 A 有额外的字段。 Yes it has but also it matches all requirements of T, this additional field doesn't ruin the fact that all properties of T are in A. Also from the practical way of thinking, if we use property lets say a and b, then if object has q, its not a problem, as we don't use this property, so nothing bad can happen.是的,它有但也符合 T 的所有要求,这个额外的字段不会破坏 T 的所有属性都在 A 中的事实。同样从实用的思维方式来看,如果我们使用属性,比如说 a 和 b,那么如果对象有 q,这不是问题,因为我们不使用这个属性,所以不会发生任何不好的事情。

FYI.供参考。 Forbidding of additional properties has no real practical sense outside of iteration over keys.除了对键的迭代之外,禁止附加属性没有真正的实际意义。 But if you are interested in such, here is full solution - Advanced TypeScript Exercises - Answer 7但如果您对此感兴趣,这里是完整的解决方案 - 高级 TypeScript 练习 - 答案 7

FYI Typescript allows excessive properties if the object is stored in a variable:仅供参考 如果对象存储在变量中,Typescript 允许过多的属性:

One final way to get around these checks, which might be a bit surprising, is to assign the object to another variable: Since squareOptions won't undergo excess property checks, the compiler won't give you an error.绕过这些检查的最后一种方法(可能有点令人惊讶)是将对象分配给另一个变量:由于 squareOptions 不会进行过多的属性检查,因此编译器不会给您错误。 https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks

So even if your function was expecting T it would work:因此,即使您的函数期望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);

In your example it's "a little bit more valid", because you are expecting anything that extends T (in this line type G<U extends T> = { ), that means anything that respect the interface T and A does.在您的示例中,它“更有效”,因为您期望任何扩展T (在此行type G<U extends T> = { ),这意味着任何尊重接口TA东西。

Other remark: Your function someFunc has no constraints on the type U, so it will accept anything:其他备注:您的函数someFunc对 U 类型没有限制,因此它将接受任何内容:

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

And to finally answer your question and to be able to forbid extra properties there is a detailed answer here: https://stackoverflow.com/a/57117594/3292234最后回答你的问题并能够禁止额外的属性,这里有一个详细的答案: https : //stackoverflow.com/a/57117594/3292234

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM