일반 유형을 사용하여 스크립트 래핑 함수를 입력합니다.
Typescript에서 일반 유형을 변경하지 않고 함수를 래핑하려면 어떻게 해야 합니까?
function x() {
console.log('Original Function');
}
function wrapper<T extends Function>(func: T): T {
// Typescript compiler error:
// Type '() => void' is not assignable to type 'T'.
return () => {
console.log('Wrapped Function');
func.call(null);
}
}
const xWrapped = wrapper(x);
xWrapped(); // logged 'Wrapped Function' & 'Original Function'
래퍼 함수는 함수를 받아들이고 정확히 동일한 형식의 서명 함수를 반환해야 한다.
형식 스크립트는 전달된 함수가 몇 개의 인수를 사용하는지 또는 무엇을 반환하는지 알 방법이 없으며 함수는 0개의 인수를 사용하고 void를 반환한다고 암시적으로 가정합니다.
현재는 기능 서명을 타이프 스크립트에 저장할 수 있는 좋은 방법이 없습니다. 그러나 이 문제를 해결할 수 있는 새로운 버전이 있습니다.
지금은 이렇게 생긴 일반적인 포장지를 만들 수 있습니다.
function wrapper<T extends (...args:any[])=>any>(func: T): T {
return <T>((...args:any[]) => {
console.log('Wrapped Function');
return func(...args);
});
}
Variadic type에 대한 제안으로 이 함수는 다음과 같이 작성될 수 있습니다.
function wrapper<...TArgs,TRet>(func:(...args:...TARGS)=>TRet) {
return (...args:...TARGS) => {
console.log("Wrapped function");
return func(...args);
}
}
여기서 중요한 차이점은 위의 솔루션이 컴파일러에게 반환 변수가 입력 변수와 같은 유형이라고 말해야 했던 캐스트가 없다는 것이다. 그러나 변수 형식에서는 변수 형식 자체를 일반적으로 입력할 수 있습니다. (변수 형식은 현재 typescript에 없으며 doget가 포함된 경우 위의 코드에 구문 오류가 있을 가능성이 있습니다.)
구현된 제안과 함께 래퍼의 작업 코드는 다음과 같습니다.
type InferArgs<T> = T extends (...t: [...infer Arg]) => any ? Arg : never;
type InferReturn<T> = T extends (...t: [...infer Arg]) => infer Res ? Res : never;
function getWrapper<TFunc extends (...args: any[]) => any>(func: TFunc)
: (...args: InferArgs<TFunc>) => InferReturn<TFunc> {
return (...args: InferArgs<TFunc>) => {
// something before
try {
return func(...args);
} finally {
// something after;
}
};
}
예시와 함께 Variadic Tupples의 사용에 관한 몇 가지 짧지만 유용한 정보는 여기에서 찾을 수 있습니다: .
변수 유형에 의존하지 않고 인수를 보존하고 내부 함수의 유형을 반환하는 대안이 있습니다.
function x(message: string): void {
console.log(`inner ${message}`);
}
export function wrapper<Args extends any[], Return>(
operation: (...operationParameters: Args) => Return,
...parameters: Args
): Return {
console.log(`outer `);
return operation(...parameters);
}
x("abc");
wrapper(x, "xyz");
// output:
//
// inner abc
// outer
// inner xyz
와 함께 호출되면 TS 컴파일러는 형식을 로 유추합니다.
호출하려고 하면 아름다운 유형의 안전과 함께 실패합니다.
다음과 같은 간단한 솔루션을 선호합니다.
function wrapFunction<TArgs extends any[], TReturn>(
targetFunction: (...parameters: TArgs) => TReturn,
): (...parameters: TArgs) => TReturn {
return (...parameters: TArgs) => {
console.log(`Hello, what is your name?`);
return targetFunction(...parameters);
};
}
// --------------- Example
const someFunction = (name: string) => {
console.log(`Hey! My name is ${name}.`);
}
const wrappedFunction = wrapFunction(someFunction);
wrappedFunction("Fábio");
산출량
[LOG]: "Hello, what is your name?"
[LOG]: "Hey! My name is Fábio."
또는 보다 일반적인 것을 원하는 경우:
export function wrapFunction<TArgs extends any[], TReturn>(
targetFunction: (...parameters: TArgs) => TReturn,
wrapperFunction: (...parameters: TArgs) => void,
): (...parameters: TArgs) => TReturn {
return (...parameters: TArgs) => {
wrapperFunction(...parameters);
return targetFunction(...parameters);
};
}
// --------------- Example
const someFunction = (name: string) => {
console.log(`Hey! My name is ${name}.`);
}
const wrapperFunction = (name: string) => {
console.log(`The wrapper - Hey! My name is ${name}.`);
}
const wrappedFunction = wrapFunction(someFunction, wrapperFunction);
wrappedFunction("Fábio");
산출량
[LOG]: "The wrapper - Hey! My name is Fábio."
[LOG]: "Hey! My name is Fábio."
여기 제가 찾은 다른 방법이 있습니다. 포장된 기능의 제네릭까지도 유지합니다.
const newFunction = ((one, two) => {
// something before
const result = oldFunction(one, two)
// something after
return result
}) as typeof oldFunction
'개발하자' 카테고리의 다른 글
Typescript에서 암시적으로 튜플 만들기 (0) | 2022.11.23 |
---|---|
Kubernetes - 포드가 컨테이너에 남아 생성 상태 (0) | 2022.11.22 |
더블 클릭 시 아나콘다 주피터 노트북에서 .ipynb를 엽니다(macOS). (0) | 2022.11.21 |
테라폼을 이전 버전으로 다운그레이드하는 방법은? (0) | 2022.11.21 |
AWS Elastic Beanstalk CLI(Win10, Python 3.6, Pip 9.0.1)를 설치할 수 없습니다. (0) | 2022.11.20 |