Reputation: 4757
In Swift there is such concept as associated types.
protocol Container {
associatedtype ItemType // Here it is.
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct IntStack: Container {
typealias ItemType = Int // Here again.
mutating func append(item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
var items = [Int]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
It's a kind of generic interfaces, but one important feature of associated types is that they can be refered from outside of the containing type.
var x: IntStack.ItemType = someIntStack.pop()
Is it possible to make somethig like this in TypeScript?
Upvotes: 15
Views: 5130
Reputation: 956
There is no such feature for associated types in Typescript at the moment.
While there isn't anything in Typescript like this?...
// WILL NOT COMPILE
interface Add<T> {
type Output;
add(other: T): Output;
}
There are alternatives that can address some of the problems that associated types address to varying degrees.
You can infer the type of passed to a generic like so
type ArrayItem<T> = T extends Array<infer I> ? I : never;
And you can use this type like this.
const number: ArrayItem<Array<number>> = 1;
You can play around with it here on the Typescript Playground here.
Say you had some types like these:
type StorageStage<T> =
| { kind: 'initial' }
| { kind: 'loading', promise: Promise<Array<T>> }
| { kind: 'loaded', storage: Array<T> };
class AsyncStorage<T> {
state: StorageStage<T> = { kind: 'initial' };
}
You can use the index syntax to get the types of these fields if they're public.
const storageStage: AsyncStorage<number>["state"] =
{ kind: 'loaded', storage: [1] };
Again, you check this out on the Typescript Playground here.
Upvotes: 11
Reputation: 7641
According the documentation, it can be something like this:
abstract class Container<ItemType> {
abstract append(item: ItemType): void;
abstract count(): number;
abstract subscript(i: number): ItemType;
}
class IntStack extends Container<number> {
private items: Array<number> = [];
append(item: number) {
this.items.push(item);
}
count(): number {
return this.items.length;
}
subscript(i: number): number {
return this.items[i];
}
// Other functions
}
In general, it is not possible to get generic type argument in runtime due to this "type" is used by typescript compiler for type checking only and does not compiles into any artifact in the result JavaScript code. You can check it in the Typescript Playground.
Inspite of it you can use some tricks, if you have a real value in runtime, as described in the Get type of generic parameter SO article.
Upvotes: -1