简体   繁体   English

Typescript:如何键入一个对象,该对象具有在实例化时不可用的必填字段?

[英]Typescript: how to type an Object that has a required field that is not available at the time of instantiation?

So I have this interface for a "full document" object: 因此,我有一个用于“完整文档”对象的接口:

export interface FullDocument {
    id: string,
    title: string,
    content: string,
    metadata: {
        author: string,
        createdAt: Date,
        updatedAt: Date
    }
    hash: Int32Array
}

In the code I want to create a new FullDocument via a var (lets assume I do that without class, just by declaring a var and that all global vars are available): 在代码中,我想通过一个变量创建一个新的FullDocument(假设我不用类就可以做到这一点,只需声明一个变量并且所有全局变量都可用):

var myNewDocument: FullDocument = {
    id: getUUID(),
    title: title,
    content: textArea,
    metadata: {
        author: author,
        createdAt: new Date(),
        updatedAt: new Date(),
    }
    hash: null
}

Now I do want to hash the document after it is instantiated / created, so initially I can not add such a hash since its not available (at least I think so), so I do that afterwards: 现在,我确实想在实例化/创建文档之后对文档进行哈希处理,因此起初我无法添加此类哈希,因为它不可用(至少我认为是这样),所以我之后再这样做:

myNewDocument.hash = hasherMethod(myNewDocument);

So question: if I have a field that is typed (as Int32Array here) but I can't add legit value in there during instantiation is my option just to do "hash?" 这样的问题:如果我有一个键入的字段(如此处的Int32Array),但是我无法在实例化期间在其中添加合法值,我的选择只是执行“哈希”吗? - the question mark that marks the property as optional? -将属性标记为可选的问号? Or is there a classic way how this is normally done? 还是有经典的方式来完成此操作?

Another approach I thought could be that I differentiate types and do: 我认为的另一种方法可能是区分类型并这样做:

  • unhashedFullDocument type unhashedFullDocument类型
  • hashed fullDocument type 散列的fullDocument类型

So how do typescripters do it? 那么打字员是怎么做到的呢?

This depends on the details, but a situation where there is a field which might not be there at one time and then might be there at another time can often be a sign of poor design (even though TypeScript aids and abets you in this with the ? notation). 这取决于细节,但是在某些情况下,某个字段可能一次不存在,然后又在另一个时间存在,这通常可能表明设计不佳(即使TypeScript通过这种方式帮助和教you了您) ?符号)。

Ask yourself: is the hash really part of the document, or is it associated with the document? 问问自己:哈希确实是文档的一部分 ,还是文档关联 If the latter is a more accurate description, then you might consider alternatives such as a weakmap, keyed by document, holding the hash --and such an approach might have other advantages as well. 如果后者是一个更准确的描述,那么您可能会考虑使用诸如文档映射键,保留哈希值弱映射之类的替代方法这样的方法也可能具有其他优点。

If you don't want to spend too much time thinking about the inner nature of documents and drawing fine distinctions between notions of "belongs to" and "associated with", then just go with an optional field. 如果您不想花太多时间思考文档的内在本质,并且不想在“属于”和“与...相关”的概念之间进行细微的区分,那么只需选择一个可选字段即可。

The alternative, of course, again depending on your use case, is to calculate the hash on as as-needed basis, if, for example, it depends on the content of the document and that content might have changed. 当然,另一选择还是取决于您的用例,例如,如果它取决于文档的内容并且该内容可能已更改,则根据需要计算哈希值。 Speaking of which, what is this hash supposed to mean, and what is it going to be used for? 说到哪个,这个散列应该是什么意思,它将被用于什么?

You use typescript to gain typesafety, so which approach you choose depends on the exact usecase: 您使用打字稿获得类型安全性,因此选择哪种方法取决于确切的用例:

 interface FullDocument {
   //...
   hash?: Int32Array;
 }

That means that FullDocument might have a hash, or it might not. 这意味着FullDocument可能具有哈希,也可能没有。 Therefore whenever you work with FullDocument types and want to access the hash you have to check if it is existing already. 因此,无论何时使用FullDocument类型并想要访问hash ,都必须检查它是否已经存在。 Now in cases were you definetly need the hash, you can just fix the type: 现在,如果您确实需要哈希,则只需修复类型:

const withHash: (FullDocument & { hash: Int32Array })[] = [];

And then you have to check if the hash is existing on every insert. 然后,您必须检查每个插入中是否存在哈希。

I agree with torazaburo that the situation you've described makes it sound like the hash maybe shouldn't be part of your object model at all. 我同意torazaburo的观点,即您所描述的情况听起来似乎完全不应该将哈希作为对象模型的一部分。

I'm envisioning a situation where you've got a component, service, or data type that requires all of its "things" to have a hash property on them, and you're thinking of adding this property to your model in order to be able to pass your objects to it. 我设想一种情况,您需要一个组件,服务或数据类型,该组件,服务或数据类型需要其所有“事物”都具有哈希属性,并且您正在考虑将此属性添加到模型中,以便能够将您的对象传递给它。

In a case like this, I'd consider using Composition: you can create a new, generic type that has two properties: an object and its hash. 在这种情况下,我会考虑使用Composition:您可以创建一个具有两个属性的新的通用类型:对象及其哈希。 Objects of this type can be used to provide a hash, without modifying other types, thereby following the Open/Closed Principle. 此类型的对象可用于提供哈希,而无需修改其他类型,从而遵循“打开/关闭原则”。

Just set it to null or undefined at instantiation. 只需在实例化时将其设置为null或未定义即可。 Unless you have the strictNullChecks flag set, all types are assignable to null and undefined. 除非设置了strictNullChecks标志,否则所有类型都可以分配为null和undefined。

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

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