interface IHuman {
name: string,
age?: number,
hungry:boolean
}
age?: number
에 optional value 값을 준 것.
age는 number
이거나 undefined
이다.
cra
와 typescript
설치
$ npx create-react-app 프로젝트명 --typescript
typescript로 설치하면 jsx
, js
파일 확장자는 tsx
, ts
로 선언된다.
🧨 but 타입스크립트 확장자가 아닌 기존과 똑같이 자바스크립트 확장자로 나온다?!?
$ npx create-react-app 프로젝트명 --template typescript
--template를 추가해서 다시 설치해보자.
tsconfig
에는 타입스크립트에 필요한 룰이 존재
- create-react-app
에 --typescript를 적용해서 프로젝트를 생성했기 때문
noImplicitAny
: false
- 변수에 타입을 선언해주지 않아도 에러가 발생하지 않음
$ npm i @types/styled-components
import styled from 'styled-components';
설치를 하고나면 styled-components에 에러가 뜨지않고, import해온 styled는 모든 type을 가질 수 있게 된다.
타입스크립트가 styled-components의 모든 타입을 알고있는 상태기 때문이다.
때문에 만약
import {createGlobalStyled} from 'styled-components';
createGlobalStyled.hello;
createGlobalStyled.hello로 실행하면 createGlobalStyled에는 hello의 타입이 없는 것을 타입스크립트가 알고있기 때문에 에러를 발생시킨다.
즉 내가 실수할 수 있는 가능성을 막아주는 것이다.
유용한 라이브러리는 사용하고 싶을 경우에
$ npm i @types/라이브러리명
으로 설치해서 타입을 선언해주자.
tsconfig.json
에
"noImplicitAny": true
'이것의 코드에 타입이 없는 경우도 있는데 이건 type을 찾지 못한 것이다.' 라는 의미
definitelyTyped
는 유명한 라이브러리만 제공해주기 때문에 알아두는 것이 좋다.
class Components <P = {}, S = {}, SS = any>
interface설정
interface IState {
counter:number
}
class App extends Components <{},IState> {
...
}
Interface 변수는 대문자로 시작하는게 좋다.
클래스형과는 달리 함수형 컴포넌트
같은 경우에는 React.FunctionComponent
를 사용해서 타입스크립트의 초기 타입을 선언해준다.
interface IProps {
count:number
const Number:React.FunctionComponent<IProps> = ({count}) => (
<Container>{count}</Container>
)
인터페이스를 사용하고 싶지 않은 경우에는
<{ count : number }>
위처럼 바로 객체형태로 타입을 선언해줄 수 있다.
React.ReactNode
: children의 타입interface IProps {
onChange: () => void
}
onChange 함수로 input의 value를 접근하기 위해서는 event arguments를 사용해야한다.
but 타입을 지정하지 않으면 onChange
함수에서 에러가 발생.
interface IInputProps {
onChange: (event: React.SyntheticEvent<HTMLInputElement>) => void
}
event arguments에 React.SyntheticEvent<HTMLInputElement>
로 타입을 선언
onChange = (event:React.SyntheticEvent<HTMLInputElement>) => {
console.log(event.target);
}
onChange함수에도 그대로 적용
Input 타입을 명시해줬기 때문에 input이 아닌 select나 다른 엘리먼트로 적용하면 에러가 난다.
이렇게 타입스크립트는 event를 정확하게 다룰 수 있도록 도와준다.
React.FormEvent
부모컴포넌트
onFormSubmit = (event:React.FormEvent) => {}
자식컴포넌트
interface IFormProps {
onFormSubmit : (event:React.FormEvent) => void
}
const Form:React.FunctionComponent<IFormProps> = ({onFormSubmit}) => (
<form onSubmit={onFormSubmit}>...</form>
)
const Container = styled.span<{isBlue:boolean}>`
color:${props => props.isBlue ? 'blue' : 'black' };
`
const Number:React.FunctionComponent<IProps> = ({count}) => (
<Container isBlue={ count > 10 }>{count}</Container>
)
styled-component는 inline으로 작성
함수형, 클래스형 컴포넌트는 interface로 작성
코드 작성하다보면 interface가 그만큼 많아지고 복잡해짐
styled-component와 함수, 클래스형 컴포넌트가 섞일 수도 있기때문에 분리해서 작성하는 것을 추천한다고 한다.
styled-components에서 theme은 variable을 정의하는 방법이다.
매번 복사, 붙여넣기하기 번거롭기 때문에 사용한다.
theme과 ThemeProvider로 정의
theme.ts
export default {
blueColor:'red'
}
index.tsx
import {ThemeProvider} from 'styled-components';
import theme from './theme'
ReactDOM.render(
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>,
document.getElementById('root')
);
컴포넌트 styled-component에 적용
const Container = styled.span<{isBlue:boolean}>`
color:${props => props.isBlue ? props.theme.blueColor : 'black' };
`
styled.d.ts
styled.d.ts
를 이용해서 theme을 자동완성 시켜줄 수 있다.
여기서 d는 definition
즉, 타입스크립트를 위해서 무언갈 정의한다는 뜻이다.
import 'styled-components';
declare module 'styled-components' {
export interface DefaultTheme { // 정의할 Theme
blueColor:string // 원하는 속성의 타입 선언
}
}