타입스크립트란 ? 자바스크립트의 단점을 보완하기 위해 만들어진 정적 타입 언어라고 생각하면 될 것 같다.
자바스크립트가 확장된 언어이기 때문에 기존 자바스크립트의 기능을 모두 사용할 수 있고 브라우저에서 실행하기 위해서 컴파일(complile)이라는 변환 과정을 거쳐야 한다.
왜 타입스크립트를 사용해야 할까? (사실 아직까지도 왜 사용하는지 이해가 안되긴 한다.. 이제 익숙해져야 할 시간인가 ..)
자바스크립트의 큰 특징 중 하나라고 생각이 들었던 것 중 하나가 되게 유연하다(?) 였다.
자바를 공부하고 넘어와서 그런지 되게 꽉 막혀있던 것들이 좀 유연해졌다! 싶었는데 이걸 이제 타입스크립트로 다시 꽉 막아야 한다.. 오히려 더 좋을지도 ㅎㅎ
인터페이스는 객체가 가져야 할 속성, 속성의 타입, 메서드 등을 명시하여 코드의 명확성과 타입 안전성을 높이는 데 도움을 준다.
이렇게 말로만 설명하면 이해가 되지 않으니까 ! 예제로 살펴보겠다
interface Person {
name : string,
age : number,
address?: string
}
let user = Person {
name : '서연',
age : 25
}
address? 속성은 선택적 속성을 나타낸다. 즉, Person을 정의할 때, addrress는 정의해도 되고 안해도 된다!
interface에 Person 객체에 대한 속성과 타입을 명시해두면, 타입에 맞지 않을 때 (만약 내가 age에 '25살' 이라고 string 타입을 명시했다면), 코드가 실행되기 전에, 타입 오류라는 오류 메시지를 나에게 제공해준다.
interface Employee extends Person {
employeeId: number
}
let employee = Employee {
name : '원식',
age : 27,
employeedId : 123,
address : '우면동'
}
Employee 인터페이스는 Person 인터페이스를 확장하여 추가적인 employeeId 속성을 정의한다.
--> 인터페이스 확장
이렇게 명시하면 :

현재, Circle 컴포넌트에 bgColor 를 props로 넘겨주어 배경색을 설정하려고 하고 있다.
--> Circle 컴포넌트가 받아서 Container 컴포넌트에 전달하며, 해당 색상으로 배경색이 설정되게 된다.
그렇다면, Circle 컴포넌트와 관련 코드를 살펴보자!

인터페이스 정의:
Container 컴포넌트:
<ContainerProps> 형태로 받았다. Circle 컴포넌트:
App 컴포넌트:
이렇게 정의할 수 있을 것 같다!
위에서 간단하게 언급하고 넘어갔었던 것 같은데,
typeScript에서는 선택적 속성을 적용할 수 있다.
자, 위의 코드에서 border-color 속성을 준다고 가정해보자.

첫번째 Circle에는 borderColor 속성을 주었고, 두번째 Circle에는 주지 않았다.

먼저, Circle 컴포넌트는 borderColor를 props로 받아오고, Container 컴포넌트로 넘겨주었다.
여기서, CircleProps에서는 borderColor?:string 으로 ? 를 사용해서 선택적 속성을 적용해 주었다. 즉, borderColor는 string 타입이거나, undefined이다! 를 의미한다. 
이렇게 친절하게도 string | undefined 알려주고 있다.
하지만, Circle 컴포넌트를 통해서 받는 Container 컴포넌트의 경우, borderColor:string 으로 무조건! string 타입으로 명시를 해주어야 하기 때문에,
현재 저 빨간색 밑줄이 나면서 오류가 발생하고 있다.
이때, 
default props를 지정해두면 된다.
borderColor ?? 'bgColor' --> borderColor이 있으면, borderColor로, 없으면 'bgColor'로 기본값을 주겠어~ 를 의미한다고 이해하면 된다.

출력값을 보면, borderColor를 준 첫번째 원은 yellow로 테두리가 생겼지만, borderColor를 주지 않은 두번째 원은 기본 값인 bgColor와 같은 색깔로 테두리가 생긴 것을 확인할 수 있다.

요렇게 {text} 값을 가져오려고 하는데, CircleProps에서 text를 text?:string 으로 명시해두면서, 선택적 속성을 주었다.
여기서, 간단하게 default 값을 전달할 수 있는데, 전달 받은 props 옆에
text = 'default text' 와 같이 default 값을 지정해 주는 것이다.
이렇게 지정해 두면,
명시안한 첫 번째 원에는 default 값인 default text 가,
두 번째 원에는 Im here이 적혀져 있을 것이다.

따란~ 진짜다
이는 타입스크립트 방식이나 타입스크립트에서 제공하는 방식이 아닌 간단한 자바스크립트의 기능이다.
유용하게 쓰이니까 꼭 알아두자!!
우리는 useState()훅을 사용하고, setState()를 사용해서 값을 변경한다.
그럼 그 값을 변경할 때, 타입스크립트를 사용해서 타입을 지정해줘야 할까?
--> 굳이 지정을 안해주어도 된다.
--> useState()를 사용해서 지정한 default값으로, 타입스크립트가 유추해서 타입을 지정해주기도 하고, default로 지정한 타입에서 왠만하면 타입이 변경되지 않기 때문이다.
그럼 간단한 counter 를 만든다고 가정해보자

counter의 타입을 명시해 둔 적이 없지만 타입스크립트가 알아서 counter= number로 판단해주어서, string 타입이나, boolean 타입으로 값을 주게 되면, 오류가 발생하는 것을 확인할 수 있다.
그래도 타입을 number, string 두개를 사용해야 하는 경우가 있을 수 있지 않을까 ?
그럴 경우에는 어떻게 해야할 까?

const [counter, setCounter] = useState<number | string>(0)으로 명시해두었다.
useState<number | string> 으로 명시를 해두면, counter의 타입을 number, string 두개 모두 받을게~ 를 의미해 setCounter(0), setCounter('hello')가 오류가 나지 않는 것을 확인할 수 있다.
타입입을 바꿀 일이 정말 드물긴 하지만, 그래도 이렇게 변경된다는 것을 알아두면 좋을 것 같다!
useState()는 크게 신경을 안써도 된다고 해도, Form 즉, 이벤트는 어떻게 주어야 할 까?

이러한 Input 태그와 Button 태그가 있다고 가정해보자.

이제, Input에서 받아오는 value의 값을 가져와야 한다. 이때 우리는 useState()를 사용할 수 있다.
const [username, setUsername] = useState('')
기본값을 '' 빈 값을 주어 string 타입으로 명시해 두었다.
이제 해야할 것들이 두가지 남아있다.
1 . onChange 이벤트
2 . onSubmit 이벤트
TypeScript 를 사용해서 이벤트 함수를 생성해보자.

먼저, onChange 함수를 생성해보자
const onchange = (e.React.ChangeEvent<HTMLInputElement>)
React.ChangeEvent<HTMLInputElement> 타입의 이벤트 객체이다.e.currentTarget는 이벤트가 발생한 요소를 가리킨다. 여기서는 입력 필드(<input>)를 가리킨다.e.currentTarget.value는 사용자가 입력한 텍스트를 의미한다.const onSubmit = (e: React.FormEvent<HTMLFormElement>)
React.FormEvent<HTMLFormElement>는 <form> 요소에서 발생하는 이벤트에 대한 정보를 포함하는 React의 이벤트 객체의 타입을 나타낸다.<form> 요소의 제출(submit) 이벤트나 유효성 검사(validation)와 같은 폼 관련 이벤트에서 사용한다.React.FormEvent는 React에서 제공하는 이벤트 객체의 일종,
<HTMLFormElement>는 폼 요소를 가리키는 HTML 태그--> DOM에서 <form> 요소의 타입을 나타낸다.
React에서는 다양한 종류의 이벤트가 발생할 수 있는 다양한 요소들이 있다. 예를 들어,
<input>요소에서는 텍스트가 입력될 때마다 ChangeEvent가 발생하고,<form>요소에서는 폼이 제출될 때 FormEvent가 발생한다.
이전에 했던 darkmode, lightmode를 기억하는가 ?!
타입스크립트와 Themes을 결합해서 darktheme, lighttheme을 만들어보자!
자 먼저, styled.d.ts 파일을 생성해줄 것이다.
--> TypeScript와 styled-components를 함께 사용해서 커스텀 테마를 정의하는 것이다.

import 'styled-components';:
styled-components 라이브러리를 가져온다. 이는 styled-components를 TypeScript 프로젝트에서 사용하겠다는 것을 의미한다.
declare module 'styled-components':
*TypeScript에서 모듈을 선언하는 구문.
이 부분은 styled-components의 타입을 확장(extend)하고자 할 때 사용된다.
export interface DefaultTheme:
styled-components의 기본 테마를 정의하는 부분이다.
DefaultTheme은 styled-components 패키지에 이미 정의되어 있는 인터페이스
여기서는 기본 테마에 새로운 속성을 추가하여 확장하고 있다.
{ textColor: string; bgColor: string; btnColor: string; }:
DefaultTheme 인터페이스를 확장하여 새로운 속성을 추가한다.
두번째로는 theme.ts 파일을 생성해준다.

import { DefaultTheme } from 'styled-components';:
styled-components 패키지에서 기본 테마(DefaultTheme) 를 가져온다. 이는 위에서 선언한 DefaultTheme 인터페이스를 가져오는 것이다.
export const lightTheme: DefaultTheme = { ... };:
lightTheme이라는 이름의 변수를 선언하고, 이를 DefaultTheme 인터페이스와 함께 타입으로 지정한다.
--> styled-components를 사용하여 두 가지의 테마를 정의하고, 이를 각각 lightTheme과 darkTheme으로 내보낸다. 이를 통해 React 애플리케이션에서 두 가지 다른 테마를 사용할 수 있다.
이제 index.jsx 에서 사용해보자

ThemeProvider 는 styled-components에서 제공하는 컴포넌트 중 하나로, React 애플리케이션에서 테마를 쉽게 관리하고 적용할 수 있도록 도와준다.
ThemeProvider의 theme prop에는 darkTheme 객체가 전달되었으므로, 애플리케이션 전체적으로 어두운 테마가 적용된다.
이제 App.jsx에서 적용해보자!

간단하게, styled-components를 사용하여 Container와 H1 컴포넌트를 정의했다.
여기서 중요한 테마와의 연동:
styled-components를 사용하여 스타일을 정의할 때, ${(props) => props.theme.XXX} 형태로 테마의 속성을 사용할 수 있다.
여기서 props.theme.XXX는 테마 객체에서 가져온 값을 나타낸다.
예를 들어, props.theme.bgColor는 테마 객체에서 정의된 bgColor 속성의 값을 의미한다.
이를 통해 테마에 따라 동적으로 스타일을 적용할 수 있다.

이렇게 Dark 모드 적용이 잘 된 것을 확인할 수 있다!