I've been banging my head against the wall for hours trying to figure out how to extract a type/interface for an object, and someone clued me into InstanceType
which is apparently not documented.
It would be awesome if some TS wiz could add this to the official docs.
If you hover on the declaration in your IDE you should see the docs:
You should also find them documented in the release notes: http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#predefined-conditional-types
Both of those routes are insufficient. It should be documented in the handbook main docs (not release notes). The point is, I never knew about InstanceType
until someone told me about it, and it was something I really needed. I would've known about it if it were in the documentation.
We do not document all the types in the standard library in the handbook. for instance ReadonlyArray
is not there, nor is ReadonlySet
, IterableIterator
, Promise
, etc..
Interesting. But then how is one supposed to learn about these? Where can I read up on what IterableIterator
or ReadonlySet
do, along with examples of usage?
We have relied on editor interaction for these. the types usually will have a JSDoc comment on them explaining what they do.
That's useful for sure. But the point I think you're missing is that nobody going through the docs would've learned about InstanceType
. And you would have to _know_ about it before looking for it via autocomplete in an editor like VS Code.
The TypeScript docs need a comprehensive API reference in the website docs, IMO. And I'd be happy to contribute, of course, but I'm too new to TypeScript.
@ffxsam I am totally agreed with you, i've been into the same situation.
@mhegazy I think TypeScript must have an api reference document, and not just the getting started one. Not everybody is from JS background, infact people ( like me ) would be taking up TS just to avoid JS, as JS is conceptually very different from a language like C# and is not very well supported by Visual Studio.
@mhegazy I believe the difference between something like Promise
and InstanceType
is that Promise
is well document as part of ES. As a developer, I know that I can use anything that is part of ES, and there is probably type information for those things that I can discovery through my editor (e.g., look at the return type of Promise.resolve(...)
).
However, for something like InstanceType
, this is _purely_ a type system construct and not mentioned or hinted at anywhere in any ES documentation such as MDN. There is no way for me to discover this construct _other_ than reading the release notes or having someone tell me about it.
I'm of the opinion that constructs that are unique to TypeScript and don't have any hints coming from ES _should_ be documented in the TypeScript handbook. I tend to agree with you though that it is unnecessary to document all of the standard library stuff that derive from ES things.
“Utility Types”, including InstanceType
are documented in the Utility Types page in the Handbook, but it’s hard to find as it’s only accessible through GitHub and not the site. There are two open issues requesting that it be added to the sidebar:
https://github.com/Microsoft/TypeScript-Handbook/issues/945
https://github.com/Microsoft/TypeScript-Handbook/issues/914
What is the usecase of the InstanceType
? Given class X
, whatever it is, we've already got X
as a type. InstanceType<typeof X> // X
- so what's the meaning of this type? All other four conditional built-in types make perfect sense to me.
It's true, InstanceType
seems kind of pointless now that I have a bit more time with TypeScript.
const spot1: InstanceType<typeof Dog> = new Dog('Spot');
const spot2: Dog = new Dog('Spot Evil Clone');
spot1.bark();
spot2.bark();
These types are exactly the same in the end.
@ducin @ffxsam Usually you don't need InstanceType
. If the class is a regular class declaration you can just use the class name to get the instance type. There are however use-cases for InstanceType
. Sometimes either the class declaration is not itself accessible (with mixins for example) or is unknown (when using generics) or is a class expression. Here are two code snippets where InstanceType
is very much needed:
Mixins:
function mixin<T extends new (...a: any[])=> any>(baseClass: T) {
class Extended extends baseClass {
public extendedMethod() {}
}
return Extended;
}
let FinalClass = mixin(class {
method() {}
})
let o: FinalClass // error FinalClass is not a type, it's just a value
let oo: InstanceType<typeof FinalClass>;
// Usually for convienence I would just add a type alias, so as to mimic a regular type declaration
// type FinalClass = InstanceType<typeof FinalClass>; // remove comment to remove error on o declaration
Factory Function:
declare function create<T extends new () => any>(c: T): InstanceType<T>
class A { }
class B { }
let a = create(A) // A
let b = create(B) // B
This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.
@dragomirtitian
Here are two factory function examples:
Below exmaple is what you shared:
declare function create<T extends new () => any>(c: T): InstanceType<T>;
class A {}
class B {}
let a = create(A); // A
let b = create(B); // B
This is my try:
declare function create2<T extends new () => any>(c: T): T;
let aa = create2(A); // A
let bb = create2(B); // B
Both of them works fine under the type system of typescript, tsc
doesn't complaint type error.
My typescript version: typescript: "^3.3.3"
So what's the meaning of using InstanceType<T>
rather than T
update
I figure it out, T
means the return type of create2
function is a class, InstanceType<T>
means the return type of create
function is an instance of the class.
I add some methods for A
and B
so that we can see the difference.
declare function create<T extends new () => any>(c: T): InstanceType<T>;
class A {
public getName() {
console.log('A');
}
}
class B {
public getAge() {
console.log(22);
}
}
let a = create(A); // A
let b = create(B); // B
a.getName(); // 'A'
b.getAge(); // 22
Above code works fine.
declare function create2<T extends new () => any>(c: T): T;
let aa = create2(A); // A
let bb = create2(B); // B
aa.getName(); // Property 'getName' does not exist on type 'typeof A'.ts(2339)
bb.getAge(); // Property 'getAge' does not exist on type 'typeof B'.ts(2339)
As you can see, tsc
complaint type error.
Most helpful comment
@ducin @ffxsam Usually you don't need
InstanceType
. If the class is a regular class declaration you can just use the class name to get the instance type. There are however use-cases forInstanceType
. Sometimes either the class declaration is not itself accessible (with mixins for example) or is unknown (when using generics) or is a class expression. Here are two code snippets whereInstanceType
is very much needed:Mixins:
Factory Function: