사용자 도구

사이트 도구


typescript:interface

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
다음 판
이전 판
typescript:interface [2018/08/03 22:45] – [Basic Example] taekgutypescript:interface [2025/04/15 10:05] (현재) – 바깥 편집 127.0.0.1
줄 58: 줄 58:
  
 아래의 코드에서 문법 오류가 일어날까요? 아래의 코드에서 문법 오류가 일어날까요?
 +<code javascript>
 interface IBook { interface IBook {
     bookName: string;     bookName: string;
줄 74: 줄 74:
 }; };
  
-printBookInfo(myBook);+printBookInfo(myBook);</code>
 원래 예상대로라면 이 코드는 문제가 있는 것이 맞습니다. myBook이라는 객체는 IBook interface type으로 지정되지 않고 parameter로 전달이 되었거든요. 하지만 이 코드는 에러없이 컴파일이 진행됩니다. 원래 예상대로라면 이 코드는 문제가 있는 것이 맞습니다. myBook이라는 객체는 IBook interface type으로 지정되지 않고 parameter로 전달이 되었거든요. 하지만 이 코드는 에러없이 컴파일이 진행됩니다.
  
줄 87: 줄 87:
 해서 저 위의 코드는 에러없이 사용할 수 있습니다. 해서 저 위의 코드는 에러없이 사용할 수 있습니다.
  
- Optional Properties+==== Optional Properties ====
  
 TypeScript interface의 모든 property와 method는 구현하는 클래스 혹은 구현 객체에서 기본적으로 모두 재정의되어야 합니다. 하지만 Optional Property( property 중 ? 가 붙어있는 property를 의미합니다. )를 이용하면 해당 property는 재정의하지 않아도 상관없습니다. 즉, 선택적으로 구현여부를 결정할 수 있는 property가 optional property입니다. TypeScript interface의 모든 property와 method는 구현하는 클래스 혹은 구현 객체에서 기본적으로 모두 재정의되어야 합니다. 하지만 Optional Property( property 중 ? 가 붙어있는 property를 의미합니다. )를 이용하면 해당 property는 재정의하지 않아도 상관없습니다. 즉, 선택적으로 구현여부를 결정할 수 있는 property가 optional property입니다.
  
 아래의 예를 가지고 살펴보겠습니다. 아래의 예를 가지고 살펴보겠습니다.
 +<code javascript>
 interface IBook { interface IBook {
     bookName: string;     bookName: string;
줄 116: 줄 116:
  
 printBookInfo(myBook); printBookInfo(myBook);
- Readonly Properties+</code> 
 +==== Readonly Properties ====
  
 readonly keyword를 이용해 객체가 처음 생성되는 시점에만 property들을 수정가능하도록 설정할 수 있습니다. readonly keyword를 이용해 객체가 처음 생성되는 시점에만 property들을 수정가능하도록 설정할 수 있습니다.
 한번 값이 세팅되면 그 후에는 수정할 수 없게됩니다. 한번 값이 세팅되면 그 후에는 수정할 수 없게됩니다.
 +<code javascript>
 interface Point { interface Point {
     readonly x: number;     readonly x: number;
줄 127: 줄 128:
  
 let p1: Point = { x: 10, y: 20 }; let p1: Point = { x: 10, y: 20 };
-p1.x = 100;    // 오류 발생+p1.x = 100;    // 오류 발생</code>
 TypeScript는 또 ReadonlyArray<T> 형태의 Array를 지원합니다. 이름에서 의미하는 것처럼 생성된 후에는 Array를 변경할 수 없습니다. TypeScript는 또 ReadonlyArray<T> 형태의 Array를 지원합니다. 이름에서 의미하는 것처럼 생성된 후에는 Array를 변경할 수 없습니다.
 +<code javascript>
 let arr: number[] = [1, 2, 3, 4]; let arr: number[] = [1, 2, 3, 4];
  
줄 138: 줄 139:
  
 arr = roArray;             // 코드 에러 arr = roArray;             // 코드 에러
-arr = roArray as number[]; // 가능+arr = roArray as number[]; // 가능</code>
 위의 코드도 쉽게 이해할 수 있습니다. 마지막 코드 정도만 주의하면 될 듯 합니다. 위의 코드도 쉽게 이해할 수 있습니다. 마지막 코드 정도만 주의하면 될 듯 합니다.
  
 이렇게 readonly property는 const와 비슷한 역할을 하게됩니다. 단 const는 변수의 선언에 사용되며 readonly는 property 지정에 사용된다는 점만 기억하시면 됩니다. 이렇게 readonly property는 const와 비슷한 역할을 하게됩니다. 단 const는 변수의 선언에 사용되며 readonly는 property 지정에 사용된다는 점만 기억하시면 됩니다.
  
- Function Types+==== Function Types ====
  
 interface는 function의 type을 지정하는데 사용할 수 있습니다. 이 경우 parameter의 리스트와 리턴타입만을 가지고 있는 함수의 선언과 비슷한 형태를 가지게 됩니다. 아래의 예를 보죠. interface는 function의 type을 지정하는데 사용할 수 있습니다. 이 경우 parameter의 리스트와 리턴타입만을 가지고 있는 함수의 선언과 비슷한 형태를 가지게 됩니다. 아래의 예를 보죠.
 +<code javascript>
 interface myInterface { interface myInterface {
     (myName: string, myAge: number): void;     (myName: string, myAge: number): void;
줄 156: 줄 157:
  
 myFunc("홍길동",30); myFunc("홍길동",30);
- Indexable Types+</code> 
 +==== Indexable Types ====
  
 JavaScript의 객체를 사용하기 위해서는 일반적으로 "." operator를 이용합니다. 일반적인 객체지향언어에서 객체를 사용하는 방식이죠. JavaScript는 추가적으로 객체를 사용하는 방법으로 배열방식을 이용할 수 있습니다. 다음과 같이 사용합니다. JavaScript의 객체를 사용하기 위해서는 일반적으로 "." operator를 이용합니다. 일반적인 객체지향언어에서 객체를 사용하는 방식이죠. JavaScript는 추가적으로 객체를 사용하는 방법으로 배열방식을 이용할 수 있습니다. 다음과 같이 사용합니다.
  
 아래의 코드는 JavaScript 코드입니다. 아래의 코드는 JavaScript 코드입니다.
 +<code javascript>
 let obj = { let obj = {
     myName: '홍길동',     myName: '홍길동',
줄 173: 줄 175:
 for(let i = 0; i< keys.length; i++) { for(let i = 0; i< keys.length; i++) {
     console.log(obj[keys[i]]);     // 배열형식을 이용     console.log(obj[keys[i]]);     // 배열형식을 이용
-}+}</code>
 위의 코드는 문법에러가 발생하지 않고 결과도 잘 출력이 됩니다. obj 객체에 접근할 때 [ ] 형태를 이용해서 key값에 접근해서 value값을 출력하는 간단한 예제입니다. 위의 코드는 문법에러가 발생하지 않고 결과도 잘 출력이 됩니다. obj 객체에 접근할 때 [ ] 형태를 이용해서 key값에 접근해서 value값을 출력하는 간단한 예제입니다.
  
 하지만 이 코드를 TypeScript로 작성하면 코드에러가 발생합니다. 해당 파일에 대한 확장자만 .js에서 .ts로 변경해보면 obj[keys[i]에서 다음과 같은 에러가 발생하는 것을 볼 수 있습니다. 하지만 이 코드를 TypeScript로 작성하면 코드에러가 발생합니다. 해당 파일에 대한 확장자만 .js에서 .ts로 변경해보면 obj[keys[i]에서 다음과 같은 에러가 발생하는 것을 볼 수 있습니다.
 +<code javascript>
 Element implicitly has an 'any' type because type  Element implicitly has an 'any' type because type 
-'{ myName: string; myAddress: string; }' has no index signature.+'{ myName: string; myAddress: string; }' has no index signature.</code>
 쉽게 말하면 index signature를 이용하지 않았기 때문에 property에 접근할 때 어떤 타입인지를 확인할 수 없어서 묵시적으로 any 타입을 이용하게 된다는 의미입니다. 하지만 우리는 TypeScript compiler 옵션 중 noImplicitAny 속성을 true로 해 놓았기 때문에 문제가 발생하는 것입니다. (noImplicitAny: true가 default로 설정됩니다.) 쉽게 말하면 index signature를 이용하지 않았기 때문에 property에 접근할 때 어떤 타입인지를 확인할 수 없어서 묵시적으로 any 타입을 이용하게 된다는 의미입니다. 하지만 우리는 TypeScript compiler 옵션 중 noImplicitAny 속성을 true로 해 놓았기 때문에 문제가 발생하는 것입니다. (noImplicitAny: true가 default로 설정됩니다.)
  
줄 187: 줄 189:
  
 좀 더 좋은 해결책은 interface로 index signature를 설정해서 사용하는 것입니다. 이걸 Indexable Type이라고 합니다. 아래의 코드처럼 interface를 이용해 index signature를 설정합니다. 좀 더 좋은 해결책은 interface로 index signature를 설정해서 사용하는 것입니다. 이걸 Indexable Type이라고 합니다. 아래의 코드처럼 interface를 이용해 index signature를 설정합니다.
 +<code javascript>
 interface IObj { interface IObj {
     [idx: string]: string;     [idx: string]: string;
줄 203: 줄 205:
 for(let i = 0; i< keys.length; i++) { for(let i = 0; i< keys.length; i++) {
     console.log(obj[keys[i]]);     // 배열형식을 이용     console.log(obj[keys[i]]);     // 배열형식을 이용
-}+}</code>
 추가적으로 union type을 이용한 다음의 코드도 살펴보시면 됩니다. 추가적으로 union type을 이용한 다음의 코드도 살펴보시면 됩니다.
 +<code javascript>
 interface IObj { interface IObj {
     [idx: string]: string | number;     [idx: string]: string | number;
줄 226: 줄 228:
 for(let i = 0; i< keys.length; i++) { for(let i = 0; i< keys.length; i++) {
     console.log(obj[keys[i]]);     // 배열형식을 이용     console.log(obj[keys[i]]);     // 배열형식을 이용
-}+}</code>
 마지막으로 앞에서 나온 readonly property를 이용하면 ReadonlyArray처럼 사용할 수 있습니다. 마지막으로 앞에서 나온 readonly property를 이용하면 ReadonlyArray처럼 사용할 수 있습니다.
 +<code javascript>
 interface ReadonlyStringArray { interface ReadonlyStringArray {
     readonly [index: number]: string;     readonly [index: number]: string;
 } }
 let myArr: ReadonlyStringArray = ["홍길동", "강감찬"]; let myArr: ReadonlyStringArray = ["홍길동", "강감찬"];
-myArr[2] = "이순신"; // 코드 오류( readonly ) +myArr[2] = "이순신"; // 코드 오류( readonly )</code> 
- Class Types+==== Class Types ====
  
 interface의 가장 일반적인 사용법은 Java나 C#언어처럼 class의 구현을 명시적으로 강제하는 것입니다. 아직 class에 대해서는 배우지 않았지만 Java같은 객체지향 언어를 해 보신 분이라면 쉽게 이해하실거라 생각됩니다. interface의 가장 일반적인 사용법은 Java나 C#언어처럼 class의 구현을 명시적으로 강제하는 것입니다. 아직 class에 대해서는 배우지 않았지만 Java같은 객체지향 언어를 해 보신 분이라면 쉽게 이해하실거라 생각됩니다.
 +<code javascript>
 interface IPerson { interface IPerson {
     [idx: string]: string | number | Function;     [idx: string]: string | number | Function;
줄 265: 줄 267:
  
 const obj = new Person("홍길동", "서울", 30); const obj = new Person("홍길동", "서울", 30);
-obj.printInfo(obj);+obj.printInfo(obj);</code>
 위와 같은 일반적인 경우가 사실은 대부분입니다. ^^; 여기에 추가적인 몇가지만 살펴보겠습니다. 이전 강좌에서 일급함수(first class function)개념에 대해서 언급했었는데 기억하시나요? 한마디로 요약하자면 “JavaScript는 함수를 값으로 취급한다” 입니다. 그래서 함수를 변수에 저장하거나 함수를 다른 함수의 인자로 넘기거나 함수의 리턴값으로 함수를 활용할 수 있는 것이지요. 위와 같은 일반적인 경우가 사실은 대부분입니다. ^^; 여기에 추가적인 몇가지만 살펴보겠습니다. 이전 강좌에서 일급함수(first class function)개념에 대해서 언급했었는데 기억하시나요? 한마디로 요약하자면 “JavaScript는 함수를 값으로 취급한다” 입니다. 그래서 함수를 변수에 저장하거나 함수를 다른 함수의 인자로 넘기거나 함수의 리턴값으로 함수를 활용할 수 있는 것이지요.
  
 그래서 다음의 JavaScript코드는 정상적으로 동작합니다. 그래서 다음의 JavaScript코드는 정상적으로 동작합니다.
 +<code javascript>
 const PersonFactory = { const PersonFactory = {
     getInstance: function(construct,name,age) {     getInstance: function(construct,name,age) {
줄 290: 줄 292:
  
 let obj = PersonFactory.getInstance(Person, "홍길동", 30); let obj = PersonFactory.getInstance(Person, "홍길동", 30);
-obj.printInfo();+obj.printInfo();</code>
 위의 코드에서 Person 생성자를 PersonFactory.getInstance 함수의 인자로 넘겨서 사용했습니다. JavaScript에서는 문제없이 잘 동작합니다. 하지만 이 코드를 그대로 TypeScript에서 작성하면 코드에러가 발생합니다. 위의 코드에서 Person 생성자를 PersonFactory.getInstance 함수의 인자로 넘겨서 사용했습니다. JavaScript에서는 문제없이 잘 동작합니다. 하지만 이 코드를 그대로 TypeScript에서 작성하면 코드에러가 발생합니다.
  
 일단 타입지정부터 엉망이니 좀 수정해서 보면 TypeScript코드는 다음과 같게 됩니다. 일단 타입지정부터 엉망이니 좀 수정해서 보면 TypeScript코드는 다음과 같게 됩니다.
 +<code javascript>
 const PersonFactory = { const PersonFactory = {
     getInstance: function(construct:any,name:string,age:number) {     getInstance: function(construct:any,name:string,age:number) {
줄 316: 줄 318:
  
 let obj = PersonFactory.getInstance(Person, "홍길동", 30); let obj = PersonFactory.getInstance(Person, "홍길동", 30);
-obj.printInfo();+obj.printInfo();</code>
 데이터 타입을 적절하게 지정해서 일단 코드 오류는 제거했습니다. 그런데 문제가 하나 있습니다. 데이터 타입을 적절하게 지정해서 일단 코드 오류는 제거했습니다. 그런데 문제가 하나 있습니다.
 +<code javascript>
 const PersonFactory = { const PersonFactory = {
     getInstance: function(construct:any,name:string,age:number) {     getInstance: function(construct:any,name:string,age:number) {
         return new construct(name,age);         return new construct(name,age);
     }     }
-};+};</code>
 위의 코드에서 생성자를 인자로 받아올 때 타입을 어떻게 지정해야 할지 몰라 일단 모든 타입에 대응되는 any로 설정했습니다. any로 설정하면 문제없지만 우리는 any를 사용하지 않습니다. 좀 심하게 표현하자면 any를 사용할꺼면 굳이 TypeScript를 할 필요가 없습니다. 여하간 이 any를 없애고 정확한 타입을 명시하려 합니다. 그런데 어떤 타입을 써야하나요? any대신 만만한 Function을 이용해 보면 다음과 같은 오류를 보실 수 있습니다. 위의 코드에서 생성자를 인자로 받아올 때 타입을 어떻게 지정해야 할지 몰라 일단 모든 타입에 대응되는 any로 설정했습니다. any로 설정하면 문제없지만 우리는 any를 사용하지 않습니다. 좀 심하게 표현하자면 any를 사용할꺼면 굳이 TypeScript를 할 필요가 없습니다. 여하간 이 any를 없애고 정확한 타입을 명시하려 합니다. 그런데 어떤 타입을 써야하나요? any대신 만만한 Function을 이용해 보면 다음과 같은 오류를 보실 수 있습니다.
- +<code javascript> 
-Cannot use 'new' with an expression whose type lacks a call or construct signature+Cannot use 'new' with an expression whose type lacks a call or construct signature</code>
 construct signature 없이 new를 사용할 수 없답니다. 그럼 이 construct signature를 어떻게 만들어야 할까요? 저 위에서는 index signature라는 걸 interface를 이용해서 선언하고 사용했습니다. 기억하시죠? 이와 비슷합니다. interface를 이용해 생성자의 signature를 지정해 줄 수 있습니다. 다음과 같이 사용합니다. construct signature 없이 new를 사용할 수 없답니다. 그럼 이 construct signature를 어떻게 만들어야 할까요? 저 위에서는 index signature라는 걸 interface를 이용해서 선언하고 사용했습니다. 기억하시죠? 이와 비슷합니다. interface를 이용해 생성자의 signature를 지정해 줄 수 있습니다. 다음과 같이 사용합니다.
 +<code javascript>
 interface IPersonConstructor { interface IPersonConstructor {
     new (n:string, a:number): Person;     new (n:string, a:number): Person;
줄 357: 줄 359:
  
 let obj = PersonFactory.getInstance(Person, "홍길동", 30); let obj = PersonFactory.getInstance(Person, "홍길동", 30);
-obj.printInfo();+obj.printInfo();</code>
 이렇게 사용하는 interface를 constructor interface 라고 표현하기도 합니다. 중요한 것은 interface로 constructor의 타입을 지정해 줄 수 있다는 것이고 construct signature라는 표현으로 interface내에 정의해서 사용합니다. 이렇게 사용하는 interface를 constructor interface 라고 표현하기도 합니다. 중요한 것은 interface로 constructor의 타입을 지정해 줄 수 있다는 것이고 construct signature라는 표현으로 interface내에 정의해서 사용합니다.
  
- interface의 확장+==== interface의 확장 ====
  
 하나의 interface는 다른 interface로 부터 상속받아서 확장될 수 있습니다. Java와 유사합니다. 다음의 코드로 이해하시면 됩니다. 하나의 interface는 다른 interface로 부터 상속받아서 확장될 수 있습니다. Java와 유사합니다. 다음의 코드로 이해하시면 됩니다.
 +<code javascript>
 interface Shape { interface Shape {
     color: string;     color: string;
줄 374: 줄 376:
 let square = <Square>{}; let square = <Square>{};
 square.color = "blue"; square.color = "blue";
-square.sideLength = 10;+square.sideLength = 10;</code>
 let square = <Square>{}; 에서 <Square> 부분이 어떤것인지 기억하시나요? 그렇습니다. Type assertions이죠. 위의 코드는 크게 어렵지 않을 듯 보입니다. 하지만 Java와 다른점이 있습니다. 동시에 여러 interface로 부터 상속을 받을 수 있다는 것이죠. 하지만 여기서 상속이라는 표현은 맞지 않습니다. 상속은 객체지향 언어에서 나오는 특성입니다. 여기서는 단지 interface의 확장일 뿐입니다. let square = <Square>{}; 에서 <Square> 부분이 어떤것인지 기억하시나요? 그렇습니다. Type assertions이죠. 위의 코드는 크게 어렵지 않을 듯 보입니다. 하지만 Java와 다른점이 있습니다. 동시에 여러 interface로 부터 상속을 받을 수 있다는 것이죠. 하지만 여기서 상속이라는 표현은 맞지 않습니다. 상속은 객체지향 언어에서 나오는 특성입니다. 여기서는 단지 interface의 확장일 뿐입니다.
 +<code javascript>
 interface Shape { interface Shape {
     color: string;     color: string;
줄 392: 줄 394:
 square.color = "blue"; square.color = "blue";
 square.sideLength = 10; square.sideLength = 10;
-square.penWidth = 5.0;+square.penWidth = 5.0;</code>
 interface는 type check를 위해 사용되기 때문에 interface로는 객체를 생성할 수 없습니다. interface는 type check를 위해 사용되기 때문에 interface로는 객체를 생성할 수 없습니다.
  
 일단 이 정도만 알아두어도 될 듯 보입니다. 내용이 생각보다 많은데 생각보다 많이 어렵지는 않습니다. 단지 헷갈릴 뿐이죠 ^^ 여러번 정독하면서 쓰임새를 알아두고 실제 코드에서 활용하면서 익히셔야 합니다. 일단 이 정도만 알아두어도 될 듯 보입니다. 내용이 생각보다 많은데 생각보다 많이 어렵지는 않습니다. 단지 헷갈릴 뿐이죠 ^^ 여러번 정독하면서 쓰임새를 알아두고 실제 코드에서 활용하면서 익히셔야 합니다.
typescript/interface.1533336333.txt.gz · 마지막으로 수정됨: 2025/04/15 10:05 (바깥 편집)