microsoft / microsoft/TypeScript

Conditional + annotation causes erroneous typing

Đang mở
#39,409 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Needs Investigation
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: 33.9.4 & 4.0.0@beta

Search Terms: Type annotation wrongly overrides generic with errors

Code

const createMatrix = <D extends number, T>(
    dimensions: D,
    initialValues: T | null = null
): Matrix<D, T> => {
    const currentDimensionLength = dimensions;
    const remainingDimensions = dimensions - 1;
    const needsRecursion = remainingDimensions > 0;

    const currentMatrix = Array(currentDimensionLength).fill(initialValues);

    const finalMatrix = needsRecursion
        ? currentMatrix.map(() =>
              createMatrix(remainingDimensions, initialValues)
          )
        : currentMatrix;

    return finalMatrix as Matrix<D, T>;
};
type Matrix<D extends number, T> = D extends 1
    ? T[]
    : D extends 2
    ? T[][]
    : D extends 3
    ? T[][][]
    : any[][][][];

Expected behavior:
Adding type annotations to variables should be compatible with the functions return signature, causing no type errors

Actual behavior:
Assigning an annotated variable to the return value of the function causes an error. The generic T is wrongly inferred to be any of array where depth < D where it should be inferred to only the base type of the nested array. Removing the annotation solves the problem but removes type safety when variable assignment happens after creation.

The problem seems to be that (when annotated) the type is inferred to be the union of each type in Matrix that's preceding the conditional that returns true.

const n1: number[] = createMatrix(1); // <- works - generic T is set to `number`
const n2: number[][] = createMatrix(2); // <- doesn't work - generic T is set to `number | number[]`
const n3: number[][][] = createMatrix(3); // <- doesn't work - generic T is set to `number | number[] | number[][]`

const n4 = createMatrix(2); // <- regular inference works - generic T is `unknown`, return type is unknown[][]
const n5: number[][] = createMatrix(2, 0); // <- works when - initialValues is set - generic T is `number`, return type is number[][]
const n6: unknown[][] = createMatrix(2); // <- works fine, as type T is unknown. A more specific annotation should constrain `unknown` to `number`

Playground Link: Link

Related Issues:
None

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Sử dụng bản tái hiện Playground được liên kết với TypeScript 3.9.4 và 4.0.0-beta, tập trung vào các lệnh gọi n2 và n3 có chú thích so với các trường hợp không có chú thích và được khởi tạo rõ ràng. Truy vết quá trình suy luận kiểu và hành vi của kiểu trả về có điều kiện cho đến khi xác định được nguồn của union tích lũy; hoàn thành khi các lệnh gọi có chú thích tạo ra các kiểu mảng lồng nhau như mong đợi mà không có lỗi.

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ó
4/5
Thời gian dự kiến
3-5 ngày
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
35/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.