#Add read-only property to class's prototype
27 messages · Page 1 of 1 (latest)
If you're strongly tied to it being a readonly prototype property, not sure you can. You may just need to bypass the typechecker there somehow.
e.g.
interface Foo { readonly bar: string }
class Foo {}
Object.assign(Foo.prototype, {bar: ""})
or just // @ts-ignore
worth noting that neither of those two solutions are all that type-safe though
you could maybe do something like this
Preview:ts interface Foo { readonly bar: string } class Foo {} ;(Foo.prototype as {bar: Foo["bar"]}).bar = "a"
which is a tiny bit better
// @ts-ignore is meant to be something of a last resort, so I'd leave it as one.
sure, but afaict Object.assign(Foo.prototype, {bar: ""}) completely bypasses the type system (in this specific context at least), so it's about as bad as (Foo.prototype as any).bar = 'a' i think
I've never done it but I made a quick function which kinda works like your solutions just I think it looks nicer using it
function assignProto<T>(constructable: new (...args: any[]) => T, data: Partial<T>) {
Object.assign(constructable.prototype, data)
}
interface Foo { readonly bar: string }
class Foo {}
assignProto(Foo,
{ bar: "" } // this is typed
)
Thanks both. Basically it's a scripting context object (think jQuery's $) with lots of objects hanging off it but one or two instance objects. I want to keep the object small by having all the static stuff on the prototype.
Sure these are all "bypassing the type system" solutions, but if you're going to bypass the type-system, it's better to do it in a more fine-grained way than // @ts-ignore which will ignore everything wrong with the line.
Maybe I'm going about this the wrong way. I just wanna attach stuff to the prototype like class methods are under the hood.
I'd probably consider a static, which would be accessed like Foo.bar not fooInstance.bar, but that is a different approach.
But yeah, I think what you're doing largely makes sense, TS just isn't completely geared towards some forms of "low-level" prototype stuff.
sure, in that case i'd probably choose (Foo.prototype as any).bar = ''
i guess there isn't anything wrong with Object.assign, just seems a little arbitrary
Yer, I thought so. Our game engine has a hacky/unsafe but very powerful runtime scripting system, new Function('$', script)(new ScriptApi(args, data)) so the easy of use of the API object wins out above all, ruling out static.
but yeah i don't think typescript has support for prototype stuff at all
other than specifying the type of MyClass.prototype
Preview:ts type DeepMutable<T> = { -readonly [K in keyof T]: DeepMutable<T[K]> } function unsafeMutable<T>(it: T): DeepMutable<T> { return it as T } interface Foo { readonly bar: string } class Foo {} unsafeMutable(Foo.prototype).bar = "a"
you may want to do something like this if you're going to be doing this kinda stuff often
as an alternative to jakob's solution
That look good to me. We're basically side-stepping TS anyway by running unknown JS at runtime so happy to go with this. Thanks again.
alternatively:
type Mutable<T> = { [K in keyof T]: T[K]; }
``` instead of `DeepMutable` - because if you're not careful and end up with very complex types (e.g. recursive types), this would never finish processing those types
!resolved