[英]How to catch at compile-time an assignment of a subtype to a supertype?
rule for TypeScript's structural type system is that
x
is compatible withy
ify
has at least the same members asx
为打字稿的结构类型系统的规则是,
x
是兼容y
如果y
具有至少相同的部件x
This allows an assignment of a variable of a subtype to a variable of a supertype. 这允许将子类型的变量分配给超类型的变量。 Is there a way to get a compile-time error regarding that assignment?
有没有办法得到关于该分配的编译时错误?
( TypeScript Playground ) ( TypeScript游乐场 )
interface SuperT {
field: string
}
// an explicitly declared subtype object for a supertype variable generates an error
const super1: SuperT = {field: 'value', extra: 1} // compile-time error: Type '{ field: string; extra: number; }' is not assignable to type 'SuperT'
function subTValue() { return {field: 'value', extra: 1} }
const super2: SuperT = subTValue() // no compile-time error, BUT HOW TO get a compile-time error here?
You want exact types which aren't directly supported. 您需要不直接支持的确切类型 。 You can do various tricks with generics and conditional types to get closer.
您可以使用泛型和条件类型来做各种技巧,以更进一步 。 Here's one way to do it indirectly:
这是间接执行此操作的一种方法:
interface SuperT {
field: string
}
type Exactly<T, U extends T> = T & Record<Exclude<keyof U, keyof T>, never>;
const asExactlySuperT = <U extends Exactly<SuperT, U>>(superT: U) => superT;
const superOkay: SuperT = asExactlySuperT({ field: "a" }); // okay
function subTValue() { return { field: 'value', extra: 1 } }
const superBad: SuperT = asExactlySuperT(subTValue()); // error!
// types of property "extra" are incompatible
The idea there is that Exactly<T, U>
will take a type T
and a candidate type U
which hopefully matches T
exactly with no extra properties. 这里的想法是,
Exactly<T, U>
将采用类型T
和候选类型U
,希望该类型与T
完全匹配而没有任何额外的属性。 If it does, then Exactly<T, U>
will equal U
. 如果是这样,则
Exactly<T, U>
将等于U
If it does not, then Exactly<T, U>
will set the property types of any extra properties to never
. 如果不是,则
Exactly<T, U>
会将任何其他属性的属性类型设置为never
。 Since asExactlySuperT<U>()
requires that U extends Exactly<SuperT, U>
, the only way that can happen is if there are no extra properties in U
. 由于
asExactlySuperT<U>()
需要U extends Exactly<SuperT, U>
,因此唯一可能发生的方法是在U
中没有额外的属性。
Hope that helps. 希望能有所帮助。 Good luck!
祝好运!
As Ray Toal found out, an answer for a very similar issue can be found here . 正如雷·托尔(Ray Toal)所发现的,可以在这里找到非常相似的问题的答案。 (And I knew this in the first place, I just wanted to check jcalz 's reaction time. Pretty impressive, @jcalz!)
(我一开始就知道这一点,我只是想检查jcalz的反应时间。非常棒,@ jcalz!)
Based on that approach, my code would look like: 基于这种方法,我的代码如下所示:
( TypeScript Playground ) ( TypeScript游乐场 )
type StrictPropertyCheck<T, TExpected, TError> = Exclude<keyof T, keyof TExpected> extends never ? {} : TError
interface SuperT {
field: string
}
function doIdentity<T extends SuperT>(a: T & StrictPropertyCheck<T, SuperT, "Only allowed properties of SuperT">) {
return a
}
function subTValue() { return { field: 'value', extra: 1 } }
const super3: SuperT = doIdentity(subTValue()) // we do get a compile-time error!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.