programing

TypeScript에서 속성을 가진 함수 개체를 만듭니다.

codeshow 2023. 4. 2. 11:43
반응형

TypeScript에서 속성을 가진 함수 개체를 만듭니다.

함수 오브젝트를 만들고 싶은데 이 오브젝트에는 몇 가지 속성이 있습니다.예를 들어 JavaScript에서는 다음을 수행합니다.

var f = function() { }
f.someValue = 3;

TypeScript에서는 이 유형을 다음과 같이 설명할 수 있습니다.

var f: { (): any; someValue: number; };

하지만 깁스를 하지 않고서는 실제로 만들 수 없습니다.예를 들어 다음과 같습니다.

var f: { (): any; someValue: number; } =
    <{ (): any; someValue: number; }>(
        function() { }
    );
f.someValue = 3;

깁스 없이 이걸 어떻게 만들겠어요?

업데이트: 이 답변은 이전 버전의 TypeScript에서 가장 적합한 솔루션이었지만 새로운 버전에서는 더 나은 옵션을 사용할 수 있습니다(기타 답변 참조).

승인된 답변은 작동하며 상황에 따라 필요할 수 있지만 객체를 빌드하기 위한 유형 안전성이 없다는 단점이 있습니다.이 기술은 정의되지 않은 속성을 추가하려고 하면 적어도 형식 오류를 발생시킵니다.

interface F { (): any; someValue: number; }

var f = <F>function () { }
f.someValue = 3

// type error
f.notDeclard = 3

「2.x 실현할 수 .x)이렇게 하다Object.assign(target, source)

예:

여기에 이미지 설명 입력

은 그 이다.Object.assign<T, U>(t: T, u: U)교차로를 반환하기 위해 입력됩니다. T & U

이것을 기존의 인터페이스로 해결하도록 강제하는 것도 간단합니다.예를 들어 다음과 같습니다.

interface Foo {
  (a: number, b: string): string[];
  foo: string;
}

let method: Foo = Object.assign(
  (a: number, b: string) => { return a * a; },
  { foo: 10 }
); 

호환되지 않는 입력으로 인한 오류:

할 수 없습니다.foo: foo: string은 foo: foo: string이다.
오류: 문자열[]에 번호를 할당할 수 없습니다(반환 유형).

주의: 오래된 브라우저를 대상으로 하는 경우 Object.assign을 polyfill해야 할 수 있습니다.

TypeScript는 선언 병합을 통해 이 문제를 처리하도록 설계되었습니다.

또한 함수를 만들고 함수에 속성을 추가하여 함수를 확장하는 JavaScript 연습에 익숙할 수 있습니다.TypeScript는 선언 병합을 사용하여 이러한 정의를 안전한 방식으로 구축합니다.

선언 병합을 통해 어떤 것이 함수와 네임스페이스(내부 모듈) 모두라고 말할 수 있습니다.

function f() { }
namespace f {
    export var someValue = 3;
}

하면 되고 두 글자를 에 쓸 수 .f() ★★★★★★★★★★★★★★★★★」f.someValue를 쓸 때.d.ts코드의 "JavaScript"를 합니다.declare:

declare function f(): void;
declare namespace f {
    export var someValue: number;
}

함수에 속성을 추가하는 것은 종종 TypeScript에서 혼란스럽거나 예상치 못한 패턴이기 때문에 피하도록 노력하지만 오래된 JS 코드를 사용하거나 변환할 때 필요할 수 있습니다.내부 모듈(네임스페이스)과 외부 모듈을 혼재시키는 것이 적절한 것은 이 시점뿐입니다.

따라서 캐스트 없이 단순히 해당 기능을 구축하여 "f"에 할당해야 하는 경우, 가능한 해결책은 다음과 같습니다.

var f: { (): any; someValue: number; };

f = (() => {
    var _f : any = function () { };
    _f.someValue = 3;
    return _f;
})();

기본적으로 할당이 완료되기 전에 시그니처와 일치하는 객체를 구성하기 위해 자체 실행 함수 리터럴을 사용합니다.유일한 이상한 점은 함수의 내부 선언이 '임의' 유형이어야 한다는 것입니다. 그렇지 않으면 컴파일러는 아직 객체에 존재하지 않는 속성에 할당하고 있다고 울부짖습니다.

EDIT: 코드를 조금 단순화했습니다.

이지만 3.1로 버전에서는 TypeScript 3.1을 하는 한 속성 할당을 할 수 .const키워드를 지정합니다.

function f () {}
f.someValue = 3; // fine
const g = function () {};
g.someValue = 3; // also fine
var h = function () {};
h.someValue = 3; // Error: "Property 'someValue' does not exist on type '() => void'"

참조온라인 예시.

바로 가기로서 ['property']액세서를 사용하여 오브젝트 값을 동적으로 할당할 수 있습니다.

var f = function() { }
f['someValue'] = 3;

이렇게 하면 유형 검사가 생략됩니다.그러나 의도적으로 동일한 방법으로 자산에 액세스해야 하므로 매우 안전합니다.

var val = f.someValue; // This won't work
var val = f['someValue']; // Yeah, I meant to do that

그러나 유형에서 속성 값을 확인하려는 경우 이 작업은 수행되지 않습니다.

매우 간단하다고는 말할 수 없지만, 확실히 가능합니다.

interface Optional {
  <T>(value?: T): OptionalMonad<T>;
  empty(): OptionalMonad<any>;
}

const Optional = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.empty = () => OptionalCreator();

궁금하시다면 이것은 TypeScript/JavaScript 버전에 대한 저의 요지에서 나온 것입니다.

된 답변: via via via the viasection via via via via via음 、 음 、 음 、 음 、 음 、 an 、 an an an an an an an 。&두 가지 추론 유형을 즉시 "추정"할 수 있습니다.

어떤 가 있습니다.from합니다.onto 오브젝트를 합니다.onto그러나 두 가지 속성 세트를 모두 포함하는 새로운 유형을 사용하여 런타임 동작을 올바르게 설명합니다.

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}

이 로우 레벨 도우미는 여전히 타입 어사션을 수행하지만 설계상 타입 세이프입니다.이 도우미를 배치하면 오퍼레이터를 사용하여 OP의 문제를 풀 타입의 안전성으로 해결할 수 있습니다.

interface Foo {
    (message: string): void;
    bar(count: number): void;
}

const foo: Foo = merge(
    (message: string) => console.log(`message is ${message}`), {
        bar(count: number) {
            console.log(`bar was passed ${count}`)
        }
    }
);

여기를 클릭하여 TypeScript Playground에서 사용해 보십시오.제약이 있다는 점에 주의해 주십시오.fooFoo, 「」의 merge해야 Foo 이름을bar로로 합니다.bad입력 에러가 발생합니다.

NB 그러나 여기에는 여전히 하나의 유형의 구멍이 있습니다.TypeScript는 형식 매개 변수를 "함수가 아님"으로 제한하는 방법을 제공하지 않습니다.두 번째 인수로 함수를 넘겨줄 수 있습니다.merge그리고 그건 통하지 않을 것이다.따라서 이것이 선언될 때까지 실행 시 이를 포착해야 합니다.

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    if (typeof from !== "object" || from instanceof Array) {
        throw new Error("merge: 'from' must be an ordinary object");
    }
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}

이것은 강한 타이핑에서 출발하지만, 당신은 할 수 있습니다.

var f: any = function() { }
f.someValue = 3;

내가 이 질문을 발견했을 때처럼 억누를 수 없을 정도로 강한 타자를 치려고 한다면 말이야안타깝게도 이것은 완전히 유효한 JavaScript에서 TypeScript가 실패하는 경우이므로 TypeScript에게 물러서라고 말해야 합니다.

"You JavaScript is perfectly valid TypeScript"는 false로 평가됩니다.(주의: 0.95 사용)

언급URL : https://stackoverflow.com/questions/12766528/build-a-function-object-with-properties-in-typescript

반응형