admin管理员组文章数量:1391783
I have a JavaScript object which dynamically allows members to be bound as accessor properties to instances of the object:
Source
function DynamicObject(obj) {
for (var prop in obj) {
Object.defineProperty(this, prop, {
get: function () { return obj[prop]; },
set: function (value) { obj[prop] = value; },
enumerable: true,
configurable: false
});
}
}
Usage
var obj = new DynamicObject({
name: "John Smith",
email: "[email protected]",
id: 1
});
When obj
is created, the members of the constructor parameter are bound to obj
as accessor properties. These show up in intellisense
I would like to know if it is possible to model this sort of behavior (including having intellisense) in TypeScript?
Notes
When you run this code in TypeScript, there is no intellisense becuase everything is any
, so TypeScript doesn't really know what's going on.
I have a JavaScript object which dynamically allows members to be bound as accessor properties to instances of the object:
Source
function DynamicObject(obj) {
for (var prop in obj) {
Object.defineProperty(this, prop, {
get: function () { return obj[prop]; },
set: function (value) { obj[prop] = value; },
enumerable: true,
configurable: false
});
}
}
Usage
var obj = new DynamicObject({
name: "John Smith",
email: "[email protected]",
id: 1
});
When obj
is created, the members of the constructor parameter are bound to obj
as accessor properties. These show up in intellisense
I would like to know if it is possible to model this sort of behavior (including having intellisense) in TypeScript?
Notes
When you run this code in TypeScript, there is no intellisense becuase everything is any
, so TypeScript doesn't really know what's going on.
-
1
I'm curious as to why you would want do this over just using a basic object literal. Just for the
configurable: false
? You could just useObject.freeze
orObject.seal
to perform similar tasks... – Heretic Monkey Commented Oct 6, 2016 at 16:35 - @MikeMcCaughan No, the advantages here are actually in the get/set functions, not configurability. – Matthew Layton Commented Oct 6, 2016 at 16:48
- So, your "real" code does something more interesting with the get/set? That's cool. – Heretic Monkey Commented Oct 6, 2016 at 16:52
2 Answers
Reset to default 5You can't. These are pletely dynamic properties, added at runtime, so you can't possibly know what they are at pile-time. I would also argue that you don't want to know what they are that early; if you have constraints to enforce, they should just be stated on their own (first example below).
If your code depends on a set of accessors, you should put those in the interface or contract directly, because you know ahead of time that you expect them and should advertise that. You can use optional properties (with the accessor defined lower) to make that simpler:
interface HasSomeProps {
foo: string;
bar?: string;
}
class DoesTheProps implements HasSomeProps {
set foo(value) {
// ...
}
}
If you have a bunch of consistent (or semi-consistent) accessors, you can define an indexer on your type like:
interface AccessStrings {
[key: string]: string;
}
That does not allow you to restrict the keys. If you want that, you should explicitly list the properties.
I would like to know if it is possible to model this sort of behavior (including having intellisense) in TypeScript?
Yes.
You can assign a generic call signature to DynamicObject
. You'll need to declare it as a variable:
var DynamicObject: new <T>(obj: T) => T = function (obj)
{
for (var prop in obj)
{
Object.defineProperty(this, prop, {
get: function () { return obj[prop]; },
set: function (value) { obj[prop] = value; },
enumerable: true,
configurable: false
});
}
} as any;
This way, IntelliSense will treat the value returned from new DynamicObject
as having the same type as the value passed in. Same property names, same property types. You'll get full autoplete and type-safety.
Live demo on TypeScript Playground
If you have trouble wrapping your head around that part in the first line, it's the same as writing the following:
// Declare type (only exists during pile-time)
var DynamicObject: new <T>(obj: T) => T;
// Assign value (during runtime)
DynamicObject = function (obj)
{
...
} as any;
本文标签: JavaScript to TypeScript Intellisense and dynamic membersStack Overflow
版权声明:本文标题:JavaScript to TypeScript: Intellisense and dynamic members - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744763842a2623913.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论