1

how can I export a type by forcing it to be an instance.

I have tried many ways, I only found one solution, creating a static getter but I would like to remove my static getter.

Here context: I would like to export a type of a instance of A from there $A.A, for ref only.


export const $A = (() => {
    class A {
        static get default() {
            return A.create();
        }
        static create() {
            return new A();
        }
        constructor() {}
    }

    return { A };
})();

i try many way, here 7 of them ! no one work instead the way 1 ! but it because i add a static getter in the js class.

export type _1 = typeof $A.A.default;
export type _2 = typeof new $A.A;
export type _3 = typeof $A.A.create();
export type _4 = typeof  $A.A();
export type _5 = typeof $A['A'];
export type _6 =  $A.A;
export type _7 = typeof new ()=>$A.A;

// example somewhere in the project, i want tell A should be a instance and not a typeof!
function foo(A:_6)

So what the syntax to emulate a instance in a ts type for export somewhere for typage usage only. My project is in js, but using ts only for help the tsserver to understand my refs when he dont.

  • So it for Intelisence in my ide only and no for generate ts=>js.

enter image description here

4
  • What exactly is generic here? I see no type parameters anywhere. Commented Mar 19, 2021 at 13:43
  • sry, miss translate , i remove generic word Commented Mar 19, 2021 at 13:44
  • See e.g. this github issue, or this qeustion. The related error message you should get is "Exported variable '$A' has or is using private name 'A'.(4025)". Commented Mar 19, 2021 at 15:00
  • this is out of context for this question, but it fine the guy above found the tool. thanks also for your time. Commented Mar 19, 2021 at 17:12

1 Answer 1

2

Preliminary note: the class A code here lacks any instance structure (no properties or methods). All non-nullish values will be assignable to that instance type; see this FAQ entry for more info. Just to avoid this weirdness, I've added a property to the example class:

const $A = (() => {
    class A {
        static get default() {
            return A.create();
        }
        static create() {
            return new A();
        }
        constructor() { }
        someStructure = 123; // add structure here
    }

    return { A };
})();

Now the compiler can tell that {someRandomThing: 123} is not compatible with the A type you're having trouble naming.


You might want to use the InstanceType<T> utility type to pull out the return type of a construct signature:

type A = InstanceType<typeof $A.A>

You could write this yourself using conditional type inference:

type AlsoA = typeof $A.A extends new (...args: any) => infer I ? I : never;

Or, you could use the method we had to use before conditional types existed: TypeScript pretends that the prototype property of a class is the same as its instance type. This isn't really true since the prototype generally only contains the methods and not other properties. But you can use it anyway:

type AlsoAlsoA = typeof $A.A.prototype;

Any of those should produce the same type.


Let's make sure it works:

function foo(a: A) { }

foo($A.A.create()) // okay
foo({ someRandomThing: 123 }) // error 
// Argument of type '{ someRandomThing: number; }' is 
// not assignable to parameter of type 'A'.

Looks good!

Playground link to code

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks you so much, export type Entity = InstanceType<typeof $Entity.Entity > ; work like a charm ! i search so long without success in the doc. " lacks any instance structure" , sure , i remove all for focus on the issu!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.