2017-10-03 1 views
1

컨텍스트

최근 타사 라이브러리의 "약속"작업을하고있었습니다. 기본적으로 라이브러리는 마지막 인수로 콜백을 사용하는 NodeJS 비동기 스타일 함수로 가득합니다. 나는. 이것과 같은 서명이 기능 : 그럼일반화 된 "promisify"함수에서 typescript 형식 유추

function cb<TResult>(
    resolve: (res: TResult) => void, 
    reject: (err: any) => void 
): (actualError, actualResult) => void { 

    return (error, result) => error ? reject(error) : resolve(result); 
} 

:

function foo(arg1: string, arg2: number, ..., callback: (error, result) => void): void

나는 Promise<T> 돌아 것들로 그들을 원래의 기능을 포장에 대한 코드를 줄이고 만들 수있는 함수를 작성하려

patchUserMetadata(userId: string, userMetadata: any): Promise<a0.Auth0UserProfile> { 
    return new Promise((resolve, reject) => 
    this.wrapped.patchUserMetadata(userId, userMetadata, cb(resolve, reject))); 
} 

linkUser(userId: string, secondaryUserToken: string): Promise<any> { 
    return new Promise((resolve, reject) => 
    this.wrapped.linkUser(userId, secondaryUserToken, cb(resolve, reject))); 
} 

// ... and so on, and on, and on... 

: 방법을 promisify, 나는 그런 코드를 작성하는 것

쉽게 볼 수 있듯이, 저는 여전히 TypeScript에 익숙하지 않고 기본적으로 바퀴를 재발 명하려고했습니다. 내 바퀴는 육각형되고 결국 나는 내 코드를 검토

누군가가 내가 저렴한 비용으로 비슷한 결과를 달성하기 위해 js-promisify을 사용할 수 있다는 지적 ... 손으로 너무 많은 포장 코드를 작성 유지했다.

module.exports = function (fun, args, self) { 
    return new Promise(function (resolve, reject) { 
    args.push(function (err, data) { 
     err && reject(err); 
     resolve(data); 
    }) 
    fun.apply(self, args); 
    }); 
}; 

내가 타이프 라이터가 아닌 자바 스크립트를 처리하고있어 이후로, 내가 더 나아가 연구의 조금을했다 : 라이브러리는 작업을 수행하는 도우미를 정의합니다. 내가 typed-promisify 따기 결국하고 코드가 지금과 같은 모습입니다 : 훨씬 깔끔한

patchUserMetadata = promisify(this.wrapped.patchUserMetadata); 

linkUser = promisify(this.wrapped.linkUser); 

, 응? 내가 방법을 정확하게 궁금

promisify 기능 작업 가까이 않습니다 얻기? 나는 소스 코드를 보면서 js-promisify의 유사한 작동하는 솔루션을 발견

export function promisify<T>(f: (cb: (err: any, res: T) => void) => void, thisContext?: any):() => Promise<T>; 
export function promisify<A, T>(f: (arg: A, cb: (err: any, res: T) => void) => void, thisContext?: any): (arg: A) => Promise<T>; 
export function promisify<A, A2, T>(f: (arg: A, arg2: A2, cb: (err: any, res: T) => void) => void, thisContext?: any): (arg: A, arg2: A2) => Promise<T>; 
// ...more overloads 

export function promisify(f: any, thisContext?: any) { 
    return function() { 
    let args = Array.prototype.slice.call(arguments); 
    return new Promise((resolve, reject) => { 
     args.push((err: any, result: any) => err !== null ? reject(err) : resolve(result)); 
     f.apply(thisContext, args); 
    }); 
    } 
} 

질문

당신이 밀접하게 promisify 보면,이 솔루션은 정말 일반화되지 않은 것을 볼 수 있습니다. 의미, 만약 내가 10 + 매개 변수와 함수를 promisify, 거기에 대한 일치하는 과부하가 필요하지 않았다. 구현은 여전히 ​​잘 작동하지만이 경우 유형 정보가 손실됩니다.

정교한 오버로드를 모두 정의하지 않고 정확한 함수 유형 (또는 시그너처, 개수 및 유형 매개 변수)을 추론하는 방법이 TypeScript에 있습니까?

나는이 [분명, 의사] 같은 뭔가를 찾고 있어요 :

export function promisify<...[TArgs], T>(
    f: (...allArgsButLastTwo: [TArgs], 
    cb: (err: any, res: T) => void) => void, 
    thisContext?: any 
): (...[TArgs]) => Promise<T>; 

export function promisify(
    ...allArgsButLastTwo: any[], 
    f: any, 
    thisContext?: any 
) { 
    return function() { 
    let args = Array.prototype.slice.call(arguments); 
    return new Promise((resolve, reject) => { 
     args.push((err: any, result: any) => err !== null ? reject(err) : resolve(result)); 
     f.apply(thisContext, args); 
    }); 
    } 
} 

나는 내가 무엇을 찾고 있어요 것은 하지 달성하는 느낌이 긴 오버로드 목록이이었다 그 이유는 저자가 사용하던 최후의 수단/절충안이 해결 될 때까지 버전 2.5로

답변