>  기사  >  웹 프론트엔드  >  TypeScript_javascript 스킬의 인터페이스에 대한 자세한 설명

TypeScript_javascript 스킬의 인터페이스에 대한 자세한 설명

WBOY
WBOY원래의
2016-05-16 15:54:071524검색

TypeScript에서는 인터페이스가 제약 조건으로 사용됩니다. JavaScript로 컴파일하면 JavaScript에는 인터페이스 개념이 없기 때문에 모든 인터페이스가 지워집니다.

간단한 예를 살펴보겠습니다.

function printLabel(labelledObj: { label: string }) {
  console.log(labelledObj.label);
}

var myObj = { size: 10, label: "Size 10 Object" };
printLabel(myObj);

그러면 이 메소드에서 labelsObj의 유형은 {label: string}입니다. 이는 다소 복잡해 보일 수 있지만 아래 myObj의 선언을 보면 이것이 크기 속성( 값은 10) 및 레이블 속성(값 "크기 10 개체")이 있는 개체입니다. 따라서 labelObj 메소드 매개변수의 유형은 {label: string}입니다. 이는 매개변수에 문자열 유형의 label 속성이 있음을 의미합니다.

그런데 이렇게 작성하면 이 방법이 아직은 좀 헷갈리는 것 같습니다. 그런 다음 인터페이스를 사용하여 이 메소드의 매개변수 유형을 정의할 수 있습니다.

interface LabelledValue {
  label: string;
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}

var myObj = { size: 10, label: "Size 10 Object" };
printLabel(myObj);

선택 속성
경우에 따라 속성이 존재할 필요가 없으므로 선택적 속성을 사용하여 정의할 수 있습니다.

interface SquareConfig {
  color?: string;
  width?: number;
}

function createSquare(config: SquareConfig): { color: string; area: number } {
  var newSquare = { color: "white", area: 100 };
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}

var mySquare = createSquare({ color: "black" });

그런 다음 SquareConfig 인터페이스를 구현하는 객체를 createSquare 메소드에 전달합니다.

완전히 필요 없는 일인데 왜 정의해야 할까요? 선택적 속성을 정의하면 전혀 정의하지 않는 것보다 두 가지 장점이 있습니다. 1. 속성이 있는 경우 유형이 제한될 수 있으며 이는 매우 중요합니다. 2. 지능형 구문 프롬프트를 얻을 수 있습니다. 실수로 메소드 본문에 색상을 작성하면 컴파일이 통과되지 않습니다.

방법 종류

자바스크립트에서는 메소드 함수가 기본형입니다. 객체 지향 사고에서 인터페이스 구현은 클래스에 의해 수행됩니다. 함수가 인터페이스를 구현할 수 있습니까? 대답은 '예'입니다.

TypeScript에서는 인터페이스를 사용하여 메소드 서명을 제한할 수 있습니다.

interface SearchFunc {
 (source: string, subString: string): boolean;
}

var mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
 var result = source.search(subString);
 if (result == -1) {
  return false;
 }
 else {
  return true;
 }
}

위 코드에서는 메소드의 시그니처를 제한하는 인터페이스를 정의합니다. 이 메소드에는 두 개의 문자열 매개변수가 있으며 부울 값을 반환합니다. 두 번째 코드에서는 이 인터페이스의 구현을 선언합니다.

컴파일러는 유형이 올바른지(매개변수 유형, 반환값 유형)만 확인하므로 매개변수 이름을 다른 것으로 변경할 수 있다는 점에 유의해야 합니다.

var mySearch: SearchFunc;
mySearch = function(src: string, sub: string) {
 var result = src.search(sub);
 if (result == -1) {
  return false;
 }
 else {
  return true;
 }
}

이것은 컴파일하여 전달할 수도 있습니다.

배열 유형
위에서 인터페이스의 메소드 유형을 정의했는데 배열 유형을 어떻게 정의해야 합니까? 매우 간단합니다.

interface StringArray {
 [index: number]: string;
}

var myArray: StringArray;
myArray = ["Bob", "Fred"];

그러면 myArray는 배열이고 인덱서는 숫자 유형이며 요소는 문자열입니다.

인터페이스 정의에 있어서 인덱서의 이름은 일반적으로 index로 되어 있습니다(물론 다른 이름으로 변경될 수도 있지만 일반적으로 index로 이름을 유지합니다). 그럼

로 바꿔보세요
interface StringArray {
 [myIndex: number]: string;
}

var myArray: StringArray;
myArray = ["Bob", "Fred"];

역시 좋습니다.

인덱서 유형은 숫자 또는 문자열만 가능하다는 점에 유의하세요.

interface Array{
  [index: number]: any;
}

interface Dictionary{
  [index: string]: any;
}

위의 두 문단을 컴파일하여 전달할 수 있습니다.

마지막으로 주의할 점은 인터페이스가 이미 배열 유형인 경우 인터페이스에 정의된 다른 속성의 유형은 배열의 요소 유형이어야 한다는 것입니다. 예:

interface Dictionary {
 [index: string]: string;
 length: number;  // error, the type of 'length' is not a subtype of the indexer
}

그러면 컴파일되지 않으며, 길이를 문자열 형식으로 변경해야 합니다.

클래스를 사용하여 인터페이스 구현
일반적인 상황에서 우리는 여전히 위와 같이 인터페이스를 직접 사용하기보다는 클래스를 사용하여 필요한 인터페이스를 구현하는 데 익숙합니다.

interface ClockInterface {
  currentTime: Date;
}

class Clock implements ClockInterface {
  currentTime: Date;
  constructor(h: number, m: number) { }
}

TypeScript에서는 EcmaScript 6과 동일하게 class 키워드를 사용하여 선언합니다.

또한 인터페이스를 사용하여 클래스에 정의된 메서드를 제한할 수 있습니다.

interface ClockInterface {
  currentTime: Date;
  setTime(d: Date);
}

class Clock implements ClockInterface {
  currentTime: Date;
  setTime(d: Date) {
    this.currentTime = d;
  }
  constructor(h: number, m: number) { }
}

TypeScript에서는 인터페이스 생성자를 정의할 수 있습니다.

interface ClockInterface {
  new (hour: number, minute: number);
}

순진하다면 다음과 같이 쓸 수도 있습니다.

interface ClockInterface {
  new (hour: number, minute: number);
}

class Clock implements ClockInterface {
  currentTime: Date;
  constructor(h: number, m: number) { }
}

이렇게 하면 안 돼요! ! ! 생성자는 정적이므로 클래스는 인터페이스의 인스턴스 부분만 구현할 수 있습니다.

그럼 이 인터페이스에 정의된 생성자는 아무런 효과가 없나요? TypeScript가 이 기능을 제공하므로 확실히 쓸모가 없습니다. 선언된 메소드는 다소 특별합니다:

interface ClockStatic {
  new (hour: number, minute: number);
}

class Clock {
  currentTime: Date;
  constructor(h: number, m: number) { }
}

var cs: ClockStatic = Clock;
var newClock = new cs(7, 30);

일반적으로 우리는 새로운 Clock을 작성하는데 여기서는 Clock 클래스를 ClockStatic 인터페이스로 지정합니다. newClock 변수의 유형은 any라는 점에 유의해야 합니다.

상속된 인터페이스
클래스와 마찬가지로 인터페이스도 확장 키워드를 사용하여 상속을 구현할 수 있습니다.

interface Shape {
  color: string;
}

interface Square extends Shape {
  sideLength: number;
}

var square = <Square>{};
square.color = "blue";
square.sideLength = 10;

물론 여러 인터페이스를 상속할 수도 있습니다.

interface Shape {
  color: string;
}

interface PenStroke {
  penWidth: number;
}

interface Square extends Shape, PenStroke {
  sideLength: number;
}

var square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

여러 인터페이스 상속을 지원하더라도 상속된 인터페이스에 정의된 동일한 이름의 속성 유형이 다른 경우 컴파일이 통과되지 않는다는 점에 유의해야 합니다.

interface Shape {
  color: string;
  test: number;
}

interface PenStroke {
  penWidth: number;
  test: string;
}

interface Square extends Shape, PenStroke {
  sideLength: number;
}

那么这段代码就无法编译通过了,因为 test 属性的类型无法确定。

同时使用上面所述的类型
如果仅能单一使用某种类型,那么这接口也未免太弱了。但幸运的是,我们的接口很强大。

interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}

var c: Counter;
c(10);
c.reset();
c.interval = 5.0;

这样就使用到三种类型了,分别是方法(接口自己是个方法)、属性、方法(定义了方法成员)。

以上所述就是本文的全部内容了,希望大家能够喜欢。

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.