Cố gắng hiểu giới hạn của 'T kéo dài suy ra U'


8

Tôi đã hiểu rằng một cái gì đó như:

type GenericExample<T> = T extends (infer U) ? U : 'bar';

bằng:

type GenericExample<T> = T extends T ? T : 'bar';

Nhưng khi mọi thứ trở nên phức tạp hơn, TypeScript phàn nàn:

type Types = 'text' | 'date' | 'articles' | 'params';

type MyExperiment<Type extends Types> =  { t : Type };

type MyExperimentsUnion = Types extends (infer U) ? MyExperiment<U> : never;
// Type 'U' does not satisfy the constraint 'Types'.
// Type 'U' is not assignable to type '"params"'.

Vì vậy, tôi muốn hỏi tại sao điều này là sai: trong trường hợp cụ thể này, sự phân phối trên liên minh sẽ diễn ra, vì vậy Uloại suy ra nên text, sau đó datevà vân vân. Vì vậy, những gì T extends (infer U)thực sự có nghĩa là gì và khi nào nó sẽ thích hợp để sử dụng nó?

Câu trả lời:


0

Tôi không nghĩ nó có nghĩa là được sử dụng theo cách bạn đang sử dụng - về cơ bản infer nên được sử dụng để "suy luận" (hoặc để giải quyết loại có thể đặt tên tốt hơn?), Phổ biến nhất là từ chung chung.

Cách bạn đang sử dụng nó, bạn đang tạo ra một loại không có bất kỳ phần "động" nào (về cơ bản nó không chung chung), có nghĩa là nó luôn giống nhau, và do đó suy ra từ một thứ luôn luôn không giống nhau . Bởi vì tại thời điểm biên dịch, bạn đã biết rằng Typeschỉ kéo dài Types & '...anything else'và vì bạn không thể xác định phần khác trong MyExperimentsUnionloại của mình ,infer nên không có nhiều sử dụng.

Ví dụ sử dụng

interface Action<T> {
    payload: T
}

type ExtractGeneric<T> = T extends Action<infer X> ? X : never

function getPayload<T extends Action<any>>(action: T): ExtractGeneric<T> {
    return action.payload;
}

const myAction = { payload: 'Test' };
const myPayloadWithResolvedType = getPayload(myAction);

Trong ví dụ trên myPayloadWithResolvedTypesẽ có stringloại được giải quyết, bởi vì nếu bạn không sử dụng infer, bạn phải chuyển loại trả về đó làm tham số thứ hai có thể như thế này:

function getPayloadNonExtract<T extends Action<U>, U>(action: T): U {
    return action.payload;
}

Đây là đường dẫn đến sân chơi.

Chúc mừng.


1
Chào người đàn ông, cảm ơn câu trả lời của bạn! Tôi phải nói rằng tôi biết mục đích chung của infertừ khóa, nhưng tôi đã hỏi câu hỏi kỳ lạ này bởi vì tôi phát hiện ra nó T extends (infer U)có giá trị trong một loại điều kiện, tôi đã ngạc nhiên về điều đó và tôi bắt đầu điều tra.
Andrea Simone Costa

1
Tôi nghĩ rằng tôi hiểu câu hỏi của bạn, nhưng tôi không chắc bạn muốn giải quyết bản thảo như thế nào U nào? Nên MyExperiment<U>là gì? Ý tôi là, Uphải là "lớp con" của Types, nhưng bản thảo không thể xác định chính xác nó là gì Uvì bạn không vượt qua bất kỳ loại nào (nó không phải là loại chung chung) và tôi không hiểu tại sao nó nên mặc định Types. Tôi đoán đó là một trong những lý do khiến bạn gặp lỗi, mặc dù tôi đồng ý rằng nó có thể mô tả nhiều hơn, nhưng có vẻ như họ đang đi với tâm trạng rằng các nhà phát triển nên biết rằng nó inferkhông được sử dụng theo cách đó.
zhuber

0

Nó có thể không đáng giá hơn hai xu nhưng:

type Types = 'text' | 'date' | 'articles' | 'params';
type MyExperiment<Type extends Types> =  { t : Type };

type MyExperimentsGenericUnion<T extends Types> = T extends (infer U) ? MyExperiment<U> : never;
// same error

type MyExperimentsUnionConstraint = any extends MyExperiment<infer U> ? MyExperiment<U> : never;
// no error

Tôi có thể nghĩ ra một vài lý do tại sao MyExperimentsUnionConstrainthoạt động nhưng MyExperimentsUnionkhông, nhưng tôi không có kiến ​​thức ngôn ngữ chuyên sâu để diễn đạt chúng sao cho hợp lý.

Để đưa ra một lời giải thích bằng ví dụ:

  • trong MyExperimentsUnion, từ Types extends U, Ucó thể được suy ra nhưTypes | 'bla' và sau đó MyExperiment<Type | 'bla'>không hoạt động.
  • trong MyExperimentsUnionConstraint, Uchỉ có thể được suy ra như một cái gì đó làm việc vớiMyExperiment
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.