Open kaleidawave opened 1 year ago
The more I investigate implementing this, the more it grows in scope.
Are we interested in ensuring that the Proxy handler returns values that respect the type definition of the proxied type? For example, we could implement a Proxy like the following:
type SomeType = {
a: number
}
const handler = {
get(_target: SomeClass, _propKey: keyof SomeType) {
return "invalid"
}
}
const proxiedType = new Proxy<SomeType>({ a: 4 }, handler)
const b: number = proxiedType.a
The above proxy is invalid because the get
method always returns a string, but the proxied type has only one property which is a number. However, even the typescript type checking as it exists today doesn't fail at compilation. From what I can tell, we could do something similar to what we did in #138 and run the handler methods where invoked to make sure it returns the type we think it will. It's also worth noting that there are many traps in the Proxy
type that can intercept just about any usage of the proxied type (eg. get
, set
, in
, new
, construct
etc.)
Hmm yes looking at this there is quite a lot to cover. I think the first step would to be get
const p = new Proxy({}, { get(target, key) { return key });
print_type(p.something)
to print "Something"
. Then from there setters and calling should be good for a MVP.
I think the last time I attempted it there were some pieces missing in the checker and I couldn't create a SpecialObject::Proxy
type never mind start using it.
Will have another look today, I think it might be possible now. I will try and get the foundation wired up, so others can tie up and test the trap logic.
Type checking is harder: how can we know that p
satisfies { a: "a", b: "b" }
? Subtyping doesn't run side effects and constant logic, so it might be more strict about what can be passed (aka disallow some some proxies that are technically valid at runtime).
Hey @PatrickLaflamme, I have added some of the Proxy constructor stuff for #146 so this looks good to start on if you want to give it a crack.
Firstly Type::SpecialObject(SpecialObject::Proxy(..))
is being created successfully by the constructor
So for the parts left to implement:
I have created a branch for the property access logic here
You basically want to get the trap type of handler and then call it with all the relevant information. As you implemented setters in #138 you should be proficient.
Once you can get the example above working in a PR
const p = new Proxy({}, { get(target, key) { return key });
print_type(p.something)
then setting and calling should be okay.
Can ignore other traps for the first iteration.
I have some ideas for subtyping but they can also be worked out later.
As much as want it not to exist. I guess it needs to be supported.
Steps
ObjectNature
which isProxy { trap: TypeId }
get_property
andset_property
to call a function ifon
has this structureTODO