#conditional types generic class
22 messages · Page 1 of 1 (latest)
no. in javascript instances of classes are just objects (usually they have a prototype chain set up, but you can also do that without classes and in any case it's not something the type system models)
if you can explain more about what specific problem you are trying to solve then i/someone else might have suggestions
Actually I think it is possible, unless I didnt get the question:
have a look: https://www.typescriptlang.org/play?#code/C4TwDgpgBAkgzgYQDYEM5xgOzsFmDGEAPACoB8UAvFCVBAB7ASYAmcs2uBEJ4xeICgH4owAE4BXaAC4oAMxRI4EANwBYAFCbQkKMjRwACmID2kMcACWEOKQrV4+9Fhx5Cduo2ZtRkiJqgoEQBvKABtAGkoS0woAGsIEBM5GgBdWRJI1KgAXwCoDPUtDQB6EqgAVTgUAHN-DXxUdCgAWRAndmD8sFMwAEYqKAByIaLAnrMAJkG+orzinWg2juMzCAtrdmoV3vWrGyJlprgyFSgymgALS3YAd0skJChLlAA3aAn+qDwWKE-J7R8KAAORMmB2aw2NkGEPM+1soRQskwEgAtgAjdZndGyHBiGI1XKnc7lEjXO4PJ6YqASAgvTB1FiyRHItGYsTY3HiAm5TRAA
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
@untold bramble Here's a shortened URL of your playground link! You can remove the full link from your message.
Preview:```ts
type IsClassInstance<T> = T extends InstanceType<any> ? true : false;
type ClassProperties<T> = IsClassInstance<T> extends true
? { [K in keyof T]: T[K] }
: T;
// Usage
class MyClass {
prop1 = '';
prop2 = 1;
}
type MyClassProperties = ClassProperties<MyClass>; // This will have prop1 and prop2
...```
you can use InstanceType to check if its an instance of something, which only applies to classes I think
that doesn't work:
type IsClassInstance<T> = T extends InstanceType<any> ? true : false;
type X = IsClassInstance<string>
// ^? - type X = true
check the definition of InstanceType. it expects to be provided a type that has a construct signature and just evaluates to the instance type the constructor returns
but any "turns off" typechecking and is infectious as usual, so InstanceType<any> is just any
however even if you used a specific class type there, it wouldn't do what they want:
class Foo { foo = '' }
type IsFooInstance<T> = T extends InstanceType<typeof Foo> ? true : false;
const fooInstance = new Foo()
type X = IsFooInstance<typeof fooInstance>
// ^? - type X = true
const fooObject = { foo: '' } // not a class instance
type Z = IsFooInstance<typeof fooObject> // but this is still `true`
// ^? - type Z = true
hmm ok thanks for the clarification
oh :O i got an answer! So its not possible i see.
i found out you can use something like this
type IsClassInstance<T> = T extends Record<string, infer _> ? false : true
const fooInstance = new Foo()
type X = IsClassInstance<typeof fooInstance>
// ^? - type X = true
type Bla = { foo: string };
type Z = IsClassInstance<{ foo: string }>
// ^? - type Z = false
infer _ is here important
But there some other issues with this
class Foo { foo = '' }
interface FooInterface { foo:string }
type IsClassInstance<T> = T extends Record<string, infer _> ? false : true
const fooInstance = new Foo()
type X = IsClassInstance<typeof fooInstance>
// ^? - type X = true
const fooObject = { foo: '' };
type Z = IsClassInstance<typeof fooObject>
// ^? - type Z = false
const fooInt:FooInterface = { foo: '' };
type D = IsClassInstance<typeof fooInt>
// ^? - type X = true meeeh!
So technically its important that its everything that can construct this way:
var = {}
und not this way
var = new Class();
IsClassInstance isn't really checking if it's a class instance (as you discovered), but rather whether the type has a (potentially implicit) index signature. in general you'll get false for type aliases and true for interfaces
IMO you should avoid fighting against the structural nature of typescript's type system. if an object has a foo property it shouldn't matter whether it was created via new or not