簡體   English   中英

打字稿:通用約束導致類型推斷選擇錯誤的候選者?

[英]typescript: generic constraints cause type inference to pick wrong candidate?

TypeScript版本: 2.6.0-dev.20170826和2.4.2

我想知道我是否遇到了一些打字稿推斷錯誤/限制,或者我的代碼是否完全錯誤。 如果代碼實際上是有效的,並且是類型推斷問題,我將向打字稿github報告一個錯誤。

我試圖限制“ Set構建器接受僅正確定義了相等性的類型(以避免出現此問題 )。

奇怪的

declare module 'strange' {
    export type WithEquality = string|number|boolean|{equals(other: any): boolean; hashCode(): number;};

    export interface Set<T> {
        add(other: T): Set<T>;
    }

    export function makeSetUnsafe<V>(...vals: V[]): Set<V>;
    export function makeSet<V extends WithEquality>(...vals: V[]): Set<V>;
}

陌生人

///<reference path="./strange.d.ts"/>

import * as S from 'strange';

const x = S.makeSetUnsafe(1,2,3);
x.add(4);

const y = S.makeSet(1,2,3);
y.add(4);

預期的行為:根據我的理解,代碼應進行編譯。 Typescript應該為兩個示例都推斷出number作為類型,並且因為numberWithEquality一個選項,並且約束是T extends WithEquality ,所以一切都很好。

實際行為:makeSetUnsafe的調用可以makeSetUnsafe編譯,但是對makeSet的調用失敗,並出現以下錯誤:

strange.ts(9,7): error TS2345: Argument of type '4' is not assignable to parameter of type '1 | 2 | 3'.

添加泛型約束以檢查Set接口的泛型類型是否具有WithEquality擴展, WithEquality導致推理選擇1|2|3而不是Tnumber

通過const y = S.makeSet<number>(1,2,3);顯式地指定類型const y = S.makeSet<number>(1,2,3); 使其構建,因此添加通用約束似乎會使類型推斷選擇其他類型。

實際上,即使更簡單,我也可以重現該問題

export type WithEquality = number;

一個很好的答案將解釋為什么此代碼是錯誤的,希望給出一個打字稿實現,以允許在類型推斷有效的情況下表達這些約束,或者確認這是打字稿的局限性。

至於發生這種情況的原因,請檢查此問題的答案:
約束為基本類型或聯合類型的類型變量,不能分配給它

您可以這樣解決:

export function makeSet<V>(...vals: Array<V & WithEquality>): Set<V>;

接着:

const y = makeSet2(1,2,3);
y.add(4); // fine
const z = makeSet(/a*/); // error

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM