问题
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:
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?
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