объявляет функцию с переопределениями с одним требуемым и несколькими выводимыми обобщениями

#typescript #generics #inferred-type

#typescript #обобщения #выводимый тип

Вопрос:

Пытаюсь сделать что-то вроде этого:

 declare function pipe<S, T1>(op1: OperatorFn<S, T1>): T1
declare function pipe<S, T1, T2>(op1: OperatorFn<S, T1>, op2: OperatorFn<T1, T2>): T2
declare function pipe<S, T1, T2, T3>(op1: OperatorFn<S, T1>, op2: OperatorFn<T1, T2>, op3: OperatorFn<T2,T3>): T3
 

Я хочу, чтобы S было обязательным, но я хочу, чтобы все остальное было выведено — все, что возвращает op1, равно T1, все, что возвращает op2, равно T2, если вы понимаете, что я имею в виду.

Я знаю, что то, что у меня есть выше, не работает, но совсем не уверен, как заставить его работать в моем файле определения.

РЕДАКТИРОВАТЬ: я знаю, что могу написать что-то вроде этого:

 export interface pipe<S> {
    <T1>(op1: OperatorFn<S, T1>): S;
    <T1,T2>(op1: OperatorFn<S, T1>, op2: OperatorFn<T1,T2>): S;
}
 

Но мне нужно объявить функцию в моем интерфейсном файле, которая затем привязана к этому интерфейсу. Не уверен, как это сделать.

РЕДАКТИРОВАТЬ # 2:

Кажется, что приведенное ниже решение моей проблемы достаточно просто:

 type pipe<S> = <T1,T2>(op1: OperatorFn<S,T1>, op2?: OperatorFn<T1,T2>) => S
 

Но тогда я не знаю, как объявить функцию, которая соответствует этому типу в моем файле определения.

Комментарии:

1. IIRC TypeScript не поддерживает предоставление только одного универсального типа, например pipe<string>(...) , если вы предоставляете какой-либо, вы должны предоставить все.

2. @jonrsharpe — Я знаю, что то, что я написал, не будет работать, но мне было интересно, могу ли я написать это по-другому, например, как в моей правке. Спасибо за комментарий!

3. Может ли человек, который закрыл голосование, предложить, какие детали или уточнения могут помочь в этом вопросе? Я буду рад их добавить.

4. «Я не знаю, как объявить функцию, которая соответствует этому типу» const impl: pipe<string> = (op) => "hi"; , например. Но я думаю, что фактический возвращаемый тип должен быть T2 if op2 , T1 в противном случае. Может быть, посмотрите, например github.com/ReactiveX/rxjs/blob/master/src/internal /.

5. @jonrsharpe — я могу написать это на typescript, но у меня возникают проблемы с записью объявлений в файл определения.

Ответ №1:

Поскольку T1 он не используется нигде, кроме как внутри функции, он позволяет вам это делать.

Это может быть легко расширено с type T2 = typeof op2 помощью и так далее.

 function pipe<S>(op1: OperatorFn<unkown, unknown>): S {
   type T1 = typeof op1 extends TEST<S, infer U> ? U : never
}
 

Вам также необходимо расширить тип S , чтобы соответствовать OperatorFn .