Typescript를 사용한 인터페이스 유형 확인 . 웹을 탐색하고 SO에서

이 질문은 TypeScript를 사용하여 클래스 유형 검사와 직접 유사합니다.

임의 유형의 변수가 인터페이스를 구현하는지 런타임에 찾아야합니다. 내 코드는 다음과 같습니다.

interface A{
    member:string;
}

var a:any={member:"foobar"};

if(a instanceof A) alert(a.member);

타이프 스크립트 놀이터에서이 코드를 입력하면 마지막 줄에 “이름 A가 현재 범위에 없습니다”라는 오류가 표시됩니다. 그러나 사실이 아닙니다. 이름이 현재 범위에 존재합니다. 변수 선언을 var a:A={member:"foobar"};편집기에서 불만없이 변경할 수도 있습니다 . 웹을 탐색하고 SO에서 다른 질문을 찾은 후 인터페이스를 클래스로 변경했지만 객체 리터럴을 사용하여 인스턴스를 만들 수 없습니다.

유형 A가 어떻게 사라질 수 있는지 궁금했지만 생성 된 자바 스크립트를 살펴보면 문제가 설명됩니다.

var a = {
    member: "foobar"
};
if(a instanceof A) {
    alert(a.member);
}

A를 인터페이스로 나타내지 않으므로 런타임 유형 검사가 불가능합니다.

동적 언어로서의 자바 스크립트에는 인터페이스 개념이 없다는 것을 이해합니다. 인터페이스 검사를 입력하는 방법이 있습니까?

타이프 스크립트 놀이터의 자동 완성 기능은 타이프 스크립트에서도 메소드를 제공한다는 것을 보여줍니다 implements. 어떻게 사용합니까?



답변

instanceof사용자 정의 유형 가드를 작성할 수 있으므로 키워드 없이 원하는 것을 얻을 수 있습니다 .

interface A{
    member:string;
}

function instanceOfA(object: any): object is A {
    return 'member' in object;
}

var a:any={member:"foobar"};

if (instanceOfA(a)) {
    alert(a.member);
}

많은 회원

개체가 유형과 일치하는지 확인하기 위해 많은 구성원을 확인해야하는 경우 대신 판별자를 추가 할 수 있습니다. 아래는 가장 기본적인 예이며 자신의 판별자를 관리해야합니다. 중복 판별자를 피하려면 패턴에 대해 더 깊이 알아야합니다.

interface A{
    discriminator: 'I-AM-A';
    member:string;
}

function instanceOfA(object: any): object is A {
    return object.discriminator === 'I-AM-A';
}

var a:any = {discriminator: 'I-AM-A', member:"foobar"};

if (instanceOfA(a)) {
    alert(a.member);
}


답변

TypeScript 1.6에서는 사용자 정의 유형 가드 가 작업을 수행합니다.

interface Foo {
    fooProperty: string;
}

interface Bar {
    barProperty: string;
}

function isFoo(object: any): object is Foo {
    return 'fooProperty' in object;
}

let object: Foo | Bar;

if (isFoo(object)) {
    // `object` has type `Foo`.
    object.fooProperty;
} else {
    // `object` has type `Bar`.
    object.barProperty;
}

Joe Yang이 언급했듯이 TypeScript 2.0부터 태그가 지정된 Union 유형을 활용할 수도 있습니다.

interface Foo {
    type: 'foo';
    fooProperty: string;
}

interface Bar {
    type: 'bar';
    barProperty: number;
}

let object: Foo | Bar;

// You will see errors if `strictNullChecks` is enabled.
if (object.type === 'foo') {
    // object has type `Foo`.
    object.fooProperty;
} else {
    // object has type `Bar`.
    object.barProperty;
}

그리고 그것은 또한 작동합니다 switch.


답변

typescript 2.0 소개 태그 연합

Typescript 2.0 기능

interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

function area(s: Shape) {
    // In the following switch statement, the type of s is narrowed in each case clause
    // according to the value of the discriminant property, thus allowing the other properties
    // of that variant to be accessed without a type assertion.
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.width * s.height;
        case "circle": return Math.PI * s.radius * s.radius;
    }
}


답변

사용자 정의 타입 가드는 어떻습니까? https://www.typescriptlang.org/docs/handbook/advanced-types.html

interface Bird {
    fly();
    layEggs();
}

interface Fish {
    swim();
    layEggs();
}

function isFish(pet: Fish | Bird): pet is Fish { //magic happens here
    return (<Fish>pet).swim !== undefined;
}

// Both calls to 'swim' and 'fly' are now okay.

if (isFish(pet)) {
    pet.swim();
}
else {
    pet.fly();
}


답변

이제 가능합니다. 방금 TypeScript완전한 리플렉션 기능을 제공 하는 향상된 버전의 컴파일러를 출시했습니다 . 메타 데이터 개체에서 클래스를 인스턴스화하고 클래스 생성자에서 메타 데이터를 검색하고 런타임에 인터페이스 / 클래스를 검사 할 수 있습니다. 여기서 확인할 수 있습니다

사용 예 :

타입 스크립트 파일 중 하나에서 다음과 같이 인터페이스와 인터페이스를 구현하는 클래스를 만듭니다.

interface MyInterface {
    doSomething(what: string): number;
}

class MyClass implements MyInterface {
    counter = 0;

    doSomething(what: string): number {
        console.log('Doing ' + what);
        return this.counter++;
    }
}

이제 구현 된 인터페이스 목록을 인쇄하겠습니다.

for (let classInterface of MyClass.getClass().implements) {
    console.log('Implemented interface: ' + classInterface.name)
}

reflec-ts로 컴파일하고 시작하십시오.

$ node main.js
Implemented interface: MyInterface
Member name: counter - member kind: number
Member name: doSomething - member kind: function

Interface메타 유형에 대한 자세한 내용은 reflection.d.ts를 참조 하십시오.

업데이트 :
전체 작업 예를 찾을 수 있습니다 여기


답변

사용자 정의 가드 가 사용 위와 동일 하지만 이번에는 화살표 함수 술어

interface A {
  member:string;
}

const check = (p: any): p is A => p.hasOwnProperty('member');

var foo: any = { member: "foobar" };
if (check(foo))
    alert(foo.member);


답변

또 다른 옵션은 다음과 같습니다. ts-interface-builder 모듈 은 TypeScript 인터페이스를 런타임 디스크립터로 변환하는 빌드 타임 도구를 제공하며, ts-interface-checker 는 객체가이를 만족하는지 확인할 수 있습니다.

OP의 예에서

interface A {
  member: string;
}

먼저 ts-interface-builder설명자와 함께 새로운 간결한 파일을 생성하는 foo-ti.ts다음과 같이 사용할 수 있습니다.

import fooDesc from './foo-ti.ts';
import {createCheckers} from "ts-interface-checker";
const {A} = createCheckers(fooDesc);

A.check({member: "hello"});           // OK
A.check({member: 17});                // Fails with ".member is not a string" 

단일 라이너 유형 보호 기능을 만들 수 있습니다.

function isA(value: any): value is A { return A.test(value); }