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?
TypeScript allows us to not only create individual types, but combine them to create more powerful use cases and completeness. There's a concept called “Intersection Types” in TypeScript that essentially allows us to combine multiple types.
In TypeScript, we can define a variable which can have multiple types of values. In other words, TypeScript can combine one or two different types of data (i.e., number, string, etc.) in a single type, which is called a union type. Union types are a powerful way to express a variable with multiple types.
In Typescript, we have three ways to work with it using: typeof: the keyword helps to check values types, like boolean, string, number, etc. instanceof: the keyword to compare the object instance with a class constructor. type guards: The powerful way to check types using typescript feature language.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With