Почему?Чтобы найти ошибки в большой базе кода, где ng.IPromise
и Promise
смешаны вместе.
Я уже сделал это для ng.IPromise, изменив это:
interface IPromise<T> {
then<TResult>(successCallback: (promiseValue: T) => IPromise<TResult>|TResult, errorCallback?: null | undefined, notifyCallback?: (state: any) => any): IPromise<TResult>;
// ...
}
к этому:
interface IPromise<T> {
then<TResult>(successCallback: (promiseValue: T) => IPromise<TResult>|TResult, errorCallback?: null | undefined, notifyCallback?: (state: any) => any): TResult extends Promise<any> ? never : IPromise<TResult>;
// ...
}
Но встроенная типизация Promise более сложна, поскольку она вводит тип PromiseLike для разрешения результата любого объекта, у которого есть метод then
:
interface PromiseLike<T> {
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
}
interface Promise<T> {
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
}
И я хочу добиться поведения, при котором каждый PromiseLike
, за исключением ng.IPromise
, разрешает .
. Попытался упростить ввод текста, чтобы лучше их понять.Таким образом, в принципе, мы можем упростить задачу до чего-то вроде этого - как изменить следующие типы:
interface Bar<T> {
then<K>(f: (value: T) => K | Bar<K>): Bar<K>;
}
interface PartialFoo<T> {
then<K>(f: (value: T) => K | PartialFoo<K>): PartialFoo<K>;
}
interface Foo<T> {
then<K>(f: (value: T) => K | PartialFoo<K>): Foo<K>;
}
так, чтобы:
let a: Foo<string>;
let b: PartialFoo<number>;
let c: Bar<number>;
let x: Foo<string> = a.then(() => a); // is ok
let y: Foo<number> = a.then(() => b); // is ok
let z: never = a.then(() => c); // returns type never, so chaining anything else will give an error
Еще одна вещь, где я на самом деле не оченьпонять, как работает Typescript, почему при изменении интерфейсов таким образом:
interface PartialFoo<T> {
then<K>(f: () => K | PartialFoo<K>): PartialFoo<K>;
}
interface Foo<T> {
then<K>(f: () => K | PartialFoo<K>): Foo<K>;
}
let a: Foo<string>;
let x = a.then(() => a);
тип для x
равен Foo<Foo<string>>
, но в случае:
interface Foo<T> {
then<K>(f: () => K | Foo<K>): Foo<K>;
}
все равно разрешаетсяFoo<string>
.Какую роль играет value: T
, если она даже не используется?