microsoft / microsoft/TypeScript
Generic values
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Go
- Star
- 111k
- Fork
- 14.3k
- Merge trung bình
- 2 ngày 4 giờ
- Pull request đã merge (30 ngày)
- 132
Mô tả
TypeScript supports generic type/interface/class declarations. These features serve as an analog of "type constructors" in other type systems: they allow us to declare a type that is parameterized over some number of type arguments.
TypeScript also supports generic functions. These serve as limited form of parametric polymorphism: they allow us to declare types whose inhabitants are parametrized over some number of type arguments. Unlike in certain other type systems however, these types can only be function types.
So for example while we can declare:
type Id = <T>(x : T) => T
const test : Id = x => x
we cannot declare (for whatever reason):
type TwoIds = <T> { id1: (x: T) => T, id2: (x: T) => T }
const test : TwoIds = { id1: x => x, id2: x => x }
One result of this limitation is that the type constructor and polymorphism features interact poorly in TypeScript. The problem applies even to function types: if we abstract a sophisticated function type into a type constructor, we can no longer universally quantify away its type parameters to get a generic function type. This is illustrated below:
// This works
type Id = <T>(x : T) => T
// This should also work
type IdT<T> = (x: T) => T
type Id = <T> IdT<T> // but is impossible to express
Another problem is that it is often useful to quantify over types other than bare functions, and TypeScript prohibits this. As an example, this prevents us from modeling polymorphic lenses:
type Lens<T, U> = {
get(obj: T): U
set(val: U, obj: T): T
}
// no way to express the following type signature
const firstItemInArrayLens: <A> Lens<A[], A> = {
get: arr => arr[0],
set: (val, arr) => [val, ...arr.slice(1)]
}
firstItemInArrayLens.get([10]) // Should be number
firstItemInArrayLens.get(["Hello"]) // Should be string
In this case, a workaround is to break down the type into functions and move all the polymorphic quantification there, since functions are the only values that are allowed to be polymorphic in TypeScript:
type ArrayIndexLens = {
get<A>(obj: A[]): A
set<A>(val: A, obj: A[]): A[]
}
const firstItemInArrayLens: ArrayIndexLens = { ... }
By contrast, in Haskell you'd simply declare an inhabitant of a polymorphic type: firstItemInArrayLens :: forall a. Lens [a] a, similarly to the pseudocode declaration const firstItemInArrayLens: <A> Lens<A[], A>:
{-# LANGUAGE ExplicitForAll #-}
data Lens s a = Lens { get :: s -> a, set :: a -> s -> s }
firstItemInArrayLens :: forall a. Lens [a] a
firstItemInArrayLens = Lens { get = _, set = _ }
In some sense TypeScript has even less of a problem doing this than Haskell, because Haskell has concerns like runtime specialization; it must turn every polymorphic expression into an actual function which receives type arguments.
TypeScript just needs to worry about assignability; at runtime everything is duck typed and "polymorphic" anyway. A more polymorphic term (or a term for which a sufficiently polymorphic type can be inferred) can be assigned to a reference of a less polymorphic type.
Today, a value of type <A> (x: A) => A is assignable where a (x: number) => number is expected, and in turn the expression x => x is assignable where a <A> (x: A) => A is expected. Why not generalize this so an <A> Foo<A> is assignable wherever a Foo<string> is expected, and it is possible to write: const anythingFooer: <A> Foo<A> = { /* implement Foo polymorphically */ }?
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Issue không xác định file, test hoặc entry point nào. Hãy bắt đầu bằng việc xem xét các ví dụ về giá trị generic và hành vi assignability được yêu cầu, sau đó xác định thiết kế type-checker cần thiết để hỗ trợ các giá trị đa hình vượt ra ngoài function. Hoàn thành có nghĩa là các generic alias và ví dụ về lens đa hình được minh họa type-check đúng như mô tả.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- typescript
- Lĩnh vực
- compilers
- Loại issue
- Tính năng
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 25/100