TypeScript에서 "클래스 선언"과 "인터페이스"의 차이점은 무엇입니까?


116

TypeScript에서 .d.ts 소스 선언 파일을 만들 때 어느 것이 바람직하며 그 이유는 무엇입니까?

declare class Example {
    public Method(): void; 
}

또는

interface Example {
    Method(): void;
}

내가 말할 수있는 차이점은 인터페이스는 정적 메서드를 가질 수 없기 때문에 클래스를 사용해야한다는 것입니다. 둘 다 JS 출력을 생성하지 않으므로 중요하지 않습니까?



두 가지 모두 JS 출력없이 동일한 작업을 수행 할 수 있기 때문에이 둘 중 하나가 서로를 사용하는 것을 설명하는 데 실제로 도움이되지 않는다고 생각합니다.
Chris

1
짧게 : 선언을 사용하면 런타임에 클래스 구현이 존재하는지 확인해야하며 인터페이스를 사용할 필요가 없습니다.
Hakim

답변:


163

interface단순히 물체의 모양을 설명하고 싶을 때 사용합니다. 인터페이스에 대한 코드 생성은 없습니다. 유형 시스템의 아티팩트 일뿐입니다. implements절이 있는지 여부에 따라 클래스의 코드 생성에 차이가 없습니다 .

declare class외부에 존재할 기존 클래스 (일반적으로 TypeScript 클래스이지만 항상 그런 것은 아님) 를 설명하려는 경우 (예 : 두 개의 .js 파일로 컴파일되는 두 개의 .ts 파일이 있고 둘 다 script태그 를 통해 포함됨) 웹 페이지에서). classusing 에서 상속하는 경우 extends(기본 유형이 declare class또는 일반 인지 여부에 관계없이 class) 컴파일러는 프로토 타입 체인과 전달 생성자를 연결하는 모든 코드를 생성합니다.

declare class인터페이스 였 어야 하는에서 상속하려고하면 생성 된 코드가 런타임 매니페스트가없는 객체를 참조하므로 런타임 오류가 발생합니다.

반대로 단순히 implement이어야하는 인터페이스 인 경우 declare class모든 멤버를 직접 다시 구현해야하며 기본 클래스 및 함수에서 코드 재사용을 활용하지 않을 것입니다. 런타임에 프로토 타입 체인을 확인하면 실제로 기본 클래스의 인스턴스가 아닌 개체가 거부됩니다.

당신이 C ++ 배경이있는 경우, 정말 살아남을 얻으려면, 당신은 대략 생각할 수 interfacetypedefdeclare classint로서 extern엄격하게이 컴파일 단위의 정의를 결여 생성자의 선언.

순수한 소비 측면에서, 사이의 유일한 차이 (하지의 새로운 유형을 추가, 필수 코드를 작성) interface그리고 declare class당신이 할 수없는 그 new인터페이스. 당신이하려는 경우, extend/ implement새로운에서 이러한 유형 중 하나 class, 당신은 절대적 사이에 올바르게 선택한해야 interface하고 declare class. 그들 중 하나만 작동합니다.

당신에게 도움이 될 두 가지 규칙 :

  • 유형의 이름이 new런타임에 실제로 존재 하는 생성자 함수 (로 호출 가능한 것)와 정렬되어 있습니까 (예 : 존재 Date하지만 JQueryStatic존재하지 않음)? 경우 에는 , 당신은 확실히 싶지interface
  • 다른 TypeScript 파일에서 컴파일 된 클래스 또는 충분히 유사한 것을 다루고 있습니까? 만약 , 사용declare class

실제로 typescript에서 인터페이스를 새로 만들 수 있습니다. 유일한 제한은 상속입니다.
Oleg Mihailik 2013-06-12

3
new인터페이스 유형 에서 연산자를 호출 할 수 없습니다 . 그러나 인터페이스에는 구성 서명이있을 수 new있습니다. 즉, 인터페이스 유형의 값에 대해 연산자를 호출 할 수 있습니다. 이것은 class구조 시그니처가 해당 유형의 표현식이 아닌 유형 이름 자체에있는 작동 방식과 는 매우 다릅니다 .
라이언 카바

인터페이스에 생성자를 추가하는 경로로 이동하는 경우 클래스의 '정적'을 제외하고 인터페이스의 유일한 멤버 여야합니다. 생성자 함수의 인터페이스를 생성 된 객체의 인터페이스와 결합하지 마십시오. 그렇게한다면 타입 시스템은 new (new x ())와 같은 어리 석음을 허용합니다. 여기서 x : Interface.
Jeremy Bell

24

인터페이스를 구현할 수 있습니다.

class MyClass implements Example {
    Method() {

    }
}

declare class구문은 실제로 TypeScript로 작성되지 않은 외부 코드에 대한 유형 정의를 추가하는 데 사용되는 반면, 구현은 "다른 곳"입니다.


그래서 선언 클래스를 TypeScript로 작성되지 않은 코드를 설명하는 데 사용해야한다고 제안하고 있습니까? 이 경우를 가정하지만 체크인 된 jquery.d.ts 파일에서 JQueryStatic은 다음에 의해 구현 된 인터페이스입니다. declare var $ : JQueryStatic 나는 이것이 클래스 $ {public static ...}
Chris

내가 생각할 수있는 유일한 이유는 사람들이 클래스를 확장하는 것을 원하지 않는 경우입니다. 인터페이스를 사용하면 전체 구현을 제공해야합니다.
Fenton 2013 년

말이된다. 그게 이유 일 것입니다.
Chris

좋아, 그래서 다른 JS 라이브러리의 선언을 가리 키려고 노력하고 있으므로 선언이 필요합니다. 코드는 일부 라이브러리 함수 (클래스)에 정적을 사용하고 있습니다. 지금까지 선언 파일에 표현 된 정적 속성이나 메서드를 아직 보지 못했습니다. 아, 네임 스페이스 나 모듈을 사용해야합니까?
젠슨 버튼 이벤트

13

평신도의 용어로, / 파일 declare에서 사용되어 현재 파일에 정의되어 있지 않더라도 해당 환경에 존재 해야하는 키워드를 컴파일러에 알려야 합니다. 그러면 Typescript 컴파일러가 이제 다른 구성 요소가 해당 변수를 제공 할 수 있음을 알고 있으므로 선언 된 개체를 사용할 때 형식 안전성을 가질 수 있습니다..tsd.tsdeclaring


6

차이 declareinterfaceTS에서 :

알리다:

declare class Example {
    public Method(): void; 
}

위의 코드 declare에서 TS 컴파일러는 클래스 Example가 선언 된 곳을 알 수 있습니다 . 이것은 클래스가 마술처럼 포함된다는 것을 의미하지 않습니다. 프로그래머는 ( declare키워드로) 선언 할 때 클래스를 사용할 수 있도록해야합니다 .

상호 작용:

interface Example {
    Method(): void;
}

interface단지 타이프 내에 존재하는 가상 구조이다. 타입 스크립트 컴파일러는 타입 검사의 목적으로 만 이것을 사용합니다. 코드가 자바 스크립트로 컴파일되면이 전체 구조가 제거됩니다. 타입 스크립트 컴파일러는 개체의 구조가 올바른지 확인하기 위해 인터페이스를 사용합니다.

예를 들어 다음 인터페이스가있는 경우 :

interface test {
  foo: number,
  bar: string,
}

이 인터페이스 유형을 가진 우리가 정의하는 객체는 인터페이스와 정확히 일치해야합니다.

// perfect match has all the properties with the right types, TS compiler will not complain.
  const obj1: test = {   
    foo: 5,
    bar: 'hey',
  }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.