microsoft / microsoft/TypeScript
Brittle circularity inherited from factory-produced class
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 Version: 3.8.3
Search Terms: extend, from, circular, constructor, class, factory
The following works like a charm. I'm able to define a circular relationship between RecordShape and ArrayShape. This is wonderful!
class ArrayShape {
constructor(public of: any) { }
}
namespace ArrayShape {
export function of(of: any) {
return class extends ArrayShape {
constructor() {
super(of);
}
}
}
}
class RecordShape {
constructor(public of: object) { }
}
namespace RecordShape {
export function of(of: any) {
return class extends RecordShape {
constructor() {
super(of);
}
}
}
}
class CycleNodeA extends RecordShape.of(() => CycleNodeB) {}
class CycleNodeB extends ArrayShape.of(() => CycleNodeA) {}
However, this starts to break down as I make it more generic. In the example below, I begin to narrow down the type passed into the ArrayShape and RecordShape constructors. The result is––once again––circularity errors :/ here is the playground.
function TypeOnly<T>() {
return (undefined as any) as T;
}
// the base from which `ArrayShape` and `RecordShape` extend
abstract class Shape<N extends string, T> {
abstract readonly name: N;
abstract readonly type: T;
}
// extracts the `T` from a given shape
type DecodeShape<S extends Shape<string, any>> =
S extends Shape<string, infer T>
? T
: never;
// for referencing shapes which aren't yet defined
type PointerShape = (() => Shape<string, any>);
// utils for treating shape and pointer shape types as if they are the same
type ShapeLike = Shape<string, any> | PointerShape;
type NormalizeShape<S extends ShapeLike> =
S extends PointerShape
? S extends (() => infer SS) ? SS : never
: S;
type DecodeShapeLike<S extends ShapeLike> = DecodeShape<NormalizeShape<S>>;
class ArrayShape<T extends ShapeLike> extends Shape<"array", DecodeShapeLike<T>[]> {
readonly name = "array";
readonly type = TypeOnly<DecodeShapeLike<T>[]>();
constructor(public elementShape: T) {
super()
}
}
namespace ArrayShape {
export function of<T extends ShapeLike>(elementShape: T) {
return class extends ArrayShape<T> {
constructor() {
super(elementShape);
}
}
}
}
class RecordShape<T extends Record<string, ShapeLike>> extends Shape<"record", {
[K in keyof T]: DecodeShapeLike<T[K]>;
}> {
readonly name = "record";
readonly type = TypeOnly<{
[K in keyof T]: DecodeShapeLike<T[K]>;
}>();
constructor(public fieldShapes: T) {
super();
}
}
namespace RecordShape {
export function of<T extends Record<string, ShapeLike>>(fieldShapes: T) {
return class extends RecordShape<T> {
constructor() {
super(fieldShapes);
}
}
}
}
const CycleNodeA = RecordShape.of({
b: () => new CycleNodeB()
}) {}
class CycleNodeB extends ArrayShape.of(() => new CycleNodeA()) {}
If the circularity error turns out to be the intended behavior, apologies––I can post on StackOverflow instead. Otherwise, any help would be greatly appreciated! Thank you!
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
Tái hiện cả hai ví dụ TypeScript Playground được liên kết bằng TypeScript 3.8.3, so sánh ví dụ vòng lặp hoạt động được với phiên bản generic báo cáo lỗi vòng lặp. Bắt đầu bằng việc điều tra cách trình kiểm tra kiểu xử lý các kiểu đệ quy thông qua các lớp do factory tạo ra và các conditional hoặc mapped types. Công việc được xem là hoàn tất khi xác định được chẩn đoán đó có chủ đích hay không và, nếu không, hành vi được báo cáo được bao phủ bằng một regression test và được sửa.
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
- Lỗi
- Độ 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