[英]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> = {
),这意味着任何尊重接口T
和A
东西。
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.