Why is a dynamic object valid to set to a class in typescript

六月ゝ 毕业季﹏ 提交于 2019-12-10 18:36:30

问题


I have played a little bit with typescript and found this:

class Greeter {
  e: number;

  p: boolean = true;
}

const xxx = new Greeter(); // true
console.log(xxx instanceof Greeter);
const xxx2: Greeter = { e: 1, p: true }; // <--- 1. why is this valid?
console.log(xxx2 instanceof Greeter); // false

const xxx3: Greeter = Object.setPrototypeOf({ e2: 1 }, Greeter.prototype); // <-- 2. no warning?
console.log(xxx2 instanceof Greeter); // true

So my Question is:

  1. Why is it valid in typescript to assign a dynamic object to a class-object, without being the class for real. It seems not to be the real class. Will this improved in the future?

  2. seems to be the hack. But there are no clean Typescript function for the types. This should be cleaner, is there a better checked function?

I use Typescript 2.4.2 with strict options.


回答1:


Why is it valid in typescript to assign a dynamic object to a class-object, without being the class for real. It seems not to be the real class.

TypeScript is a structural language, not a nominal language. This means the structures are checked, and any compatible type can be used. Once you start leaning on this language feature, nominal typing will drive you nuts.

Will this improved in the future?

It can't be improved! Structural types rock :).

But I suppose the proper answer is "no - this is by design".

const xxx3: Greeter = Object.setPrototypeOf({ e2: 1 }, Greeter.prototype); seems to be the hack. But there are no clean Typescript function for the types. This should be cleaner, is there a better checked function?

This one needs a little deconstruction.

The first part is that there is a dynamic type in TypeScript: any. Anything that has the type any is like a shapeshifter. It can literally be any type.

You can use any whenever you want the compiler to stay out of the way and allow you to use dynamic types. (Dynamic as in "the type can change dynamically", I notice you describe your object literal as dynamic - but I'm talking about the official dynamic type here).

When you call Object.setPrototypeOf(...) it returns one of these special dynamic types, with the type any.

That means, when you assign it to the variable that has the type Greeter it is allowable, because you have an any type.

Although this may be frustrating your attempts to do something, I'm sure what you want to achieve is possible - so feel free to ask how to achieve whatever it is you need to do and I'm sure we'll come up with a way to help




回答2:


As typescript does a compile time check only.

If you use the link below and paste your code and get the JavaScript

const xxx2: Greeter = { e: 1, p: true }; 

converts to -->

var xxx2 = { e: 1, p: true }; 

Which is just a object and doesn't know anything about class Greeter

https://www.typescriptlang.org/play/index.html




回答3:


Got here from your related Github issue.

@Fenton's correct answer is laudable evangelism for structural typing as supported in TypeScript. For those occasions where one finds oneself entertaining thoughts of the forbidden fruit of nominal typing, however, there are indeed workarounds:

I suggest giving Greeter a private member so you can no longer assign an object literal to it. Private class members seem to be the "standard" TypeScript workaround for nominal typing.

Example:

class Greeter {
  private _nominal = true; // add something like this
  e: number;
  p: boolean = true;
}

const xxx = new Greeter();
const xxx2: Greeter = { e: 1, p: true }; // error, missing _nominal
const xxx3: Greeter = { e: 1, p: true, _nominal: true }; // error, _nominal is private

Does that work for you? That will at least make it more difficult to shoot yourself in the foot, although if you really try, you will succeed:

// don't do this
const xxx4: Greeter = function() { return "ha ha fooled you";} as any as Greeter; 

Hope that helps; good luck!



来源:https://stackoverflow.com/questions/47579148/why-is-a-dynamic-object-valid-to-set-to-a-class-in-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!