비엔 Vien 2025. 5. 18. 11:10

TypeScript

: 자바스크립트를 기반으로 하되 몇가지 기능(정적 타입)을 더 추가함

ㄴ 경고해주는 기능 같은것....\\

ㄴㄴ (타입표기 ':타입' 식으로 )

 

 

 

r기본형 타입

let age: number;

let name: string;

...

 

좀 더 복잡한 친구들

let hobbies: string[];



let person: {
    name: string;
    age: number;
}

 

 

타입 추론  - 불필요하게 타입을 추론할 필요는 없다

let course = 'aaa';

굳이 let course :String = 'aaa'; 할 필요 X

 

유니온 타입

let a: string | string[];

 

 

타입 별칭⭐️

type Person = {
    name: string;
    age: number;
};


let person: Person;

let people: Person[];

 

 

함수

function(a:neber, b:number){
    return a+b;
}


//but 필요한게 아닌 경우 반환값 타입은 굳이 쓰지 말기
function(a:neber, b:number) :number{
    return a+b;
}


function print(value:any){
    console.log(value);
}

 

제네릭

function insertAtBeginning<T>(array: T[], value: T) {
    const newArray = [value, ...array];
    return newArray;
}

const demoArray = [1, 2, 3];
const updatedArray = insertAtBeginning(demoArray, -1); // [-1, 1, 2, 3]

const stringArray = insertAtBeginning(['b', 'c'], 'a'); // ['a', 'b', 'c']

 

보통 함수나 클래스에서 다양한 타입을 다루고 싶을 때 모든 타입에 대응하려고 any를 쓰면 타입 안정성이 깨짐..

>> 제네릭을 쓰면 타입을 나중에 결정하되, 안전하게 사용할 수 있음


 

 

//App.jsx

import React from 'react';

const Todos: React.FC<{ items: string[] }> = (props) => {
    return (
        <ul>
            {props.items.map(item => <li key={item}>{item}</li>)}
        </ul>
    );
};

export default Todos;


//Todos.tsx
import React from 'react';


//props로 items라는 string 배열을 받아옴
//제네릭으로 props 타입을 지정
const Todos: React.FC<{ items: string[] }> = (props) => {
    return (
        <ul>
            {props.items.map(item => <li key={item}>{item}</li>)}
        </ul>
    );
};

export default Todos;

 

 

 

 

typescript는 class 에 추가할 속성이나 프로퍼티가 잇을 경우 생성자를 통해 추가할 필요 없음

//Todo.tsx
import React from "react";
import Todo from '../models/todos';

const Todos: React.FC<{ items: Todo[] }> = (props) => {
  return (
    <ul>
      {props.items.map((item) => (
        <li key={item.id}>{item.text}</li>
      ))}
    </ul>
  );
};

export default Todos;


//App.tsx
import Todos from './components/Todos';
import Todo from './models/todos';

function App() {

  const todos = [new Todo('Learn React'), new Todo('Learn TypeScript')];
  return (
    <div>
      <Todos items={todos} />
    </div>
  );
}

export default App;



//todos.ts
class Todo{
    id: string;
    text: string;

	//생성자에서 todoText를 받아 text 속성에 저장하고, id는 현재 시간을 기반으로 자동 생성
    //TypeScript에서는 이렇게 생성자 내부에서 프로퍼티를 초기화해주면 따로 this.text = ...처럼 하지 않고도 자동으로 클래스에 속성 추가가 됨
    constructor(todoText: string) {
        this.text = todoText;
        this.id = new Date().toISOString(); // 고유한 ID 자동 생성
    }
}

export default Todo;

 

 

//TodoItem.tsx
//props로 text만 전달받고, 내부에서는 해당 텍스트만 렌더링
const TodoItem: React.FC<{text: string }> = (props) => {
    return <li>{props.text}</li>
};

export default TodoItem;



//Todo.tsx
import React from "react";

import TodoItem from './TodoItem';
import Todo from '../models/todos';

const Todos: React.FC<{ items: Todo[] }> = (props) => {
  return (
    <ul>
      {props.items.map((item) => (
      // 컴포넌트 별도로 분리하여,,
        <TodoItem key={item.id} text={item.text}/>
      ))}
    </ul>
  );
};

export default Todos;

 

 

용자에게 입력창 제공

//NewTodos.tsx
const NewTodo = () => {
  const submitHandler = (event: React.FormEvent) => {
    event.preventDefault();
  };

  return (
    <form onSubmit={submitHandler}>
      <label htmlFor="text">Todo text</label>
      <input type="text" id="text" />
      <button>Add Todo</button>
    </form>
  );
};

export default NewTodo;

 

타입스크립트에서 ref 사용시 더 많은 정보 알려줘야 함

(해당 레퍼런스에 저장 될 데이터가 어떤 타입인지 알려줘야 함

/?NewTodo.tsx
import { useRef } from "react";

const NewTodo = () => {
  const todoTextInputRef = useRef<HTMLInputElement>(null);

  const submitHandler = (event: React.FormEvent) => {
    event.preventDefault();

    const enteredText = todoTextInputRef.current!.value;
    
    if (enteredText?.trim().length === 0) {
        // 예시: 값이 비었을 경우 처리
        return;
    }

};

  return (
    <form onSubmit={submitHandler}>
      <label htmlFor="text">Todo text</label>
      <input type="text" id="text" ref={todoTextInputRef} />
      <button>Add Todo</button>
    </form>
  );
};

export default NewTodo;

 

 

 

//onAddTodo가 함수 타입이어야 한다는 제네릭...

//NewTodo.tsx
import { useRef } from "react";

//onAddTodo가 함수 타입이어야 한다는 제네릭...
const NewTodo: React.FC<{onAddTodo: (text: string) => void}> = (props) => {
  const todoTextInputRef = useRef<HTMLInputElement>(null);

  const submitHandler = (event: React.FormEvent) => {
    event.preventDefault();

    const enteredText = todoTextInputRef.current!.value;
    
    if (enteredText?.trim().length === 0) {
        // 예시: 값이 비었을 경우 처리
        return;
    }


    props.onAddTodo(enteredText);

};

  return (
    <form onSubmit={submitHandler}>
      <label htmlFor="text">Todo text</label>
      <input type="text" id="text" ref={todoTextInputRef} />
      <button>Add Todo</button>
    </form>
  );
};

export default NewTodo;



//App.tsx
import Todos from "./components/Todos";
import Todo from "./models/todos";

import NewTodo from "./components/NewTodos";

function App() {
  const todos = [new Todo("Learn React"), new Todo("Learn TypeScript")];

  const addTodoHandler = (todoText: string) => {

  };

  return (
    <div>
      <NewTodo onAddTodo={addTodoHandler}/>
      <Todos items={todos} />
    </div>
  );
}

export default App;

 

 

 

state 업데이트

import {useState} from 'react';

import Todos from "./components/Todos";
import Todo from "./models/todos";

import NewTodo from "./components/NewTodos";

function App() {
  const [todos, setTodos]  = useState<Todo[]>([]);
  const addTodoHandler = (todoText: string) => {
     const newTodo = new Todo(todoText);

     //상태 업데이트 
     //newTodo를 마지막에 추가한 새로운 배열을 만들어서 상태 업데이트
     setTodos((prevTodos) => {
      return prevTodos.concat(newTodo);
     });
  };

  return (
    <div>
      <NewTodo onAddTodo={addTodoHandler}/>
      <Todos items={todos} />
    </div>
  );
}

export default App;

 

 

 

 

 

css 추가하기.. 그냥

'

 

클릭을 통한 삭제 

import { useState } from "react";

import Todos from "./components/Todos";
import Todo from "./models/todos";

import NewTodo from "./components/NewTodos";

function App() {
  const [todos, setTodos] = useState<Todo[]>([]);
  const addTodoHandler = (todoText: string) => {
    const newTodo = new Todo(todoText);

    setTodos((prevTodos) => {
      return prevTodos.concat(newTodo);
    });
  };

  const removeTodoHandler = (todoId: string) => {
    setTodos((prevTodos) => {
      return prevTodos.filter((todo) => todo.id !== todoId);
    });
  };

  return (
    <div>
      <NewTodo onAddTodo={addTodoHandler} />
      <Todos items={todos} onRemoveTodo={removeTodoHandler} />
    </div>
  );
}

export default App;

 

 

.bind() : 실행할 함수 미리 정의 가능

import React from "react";

import TodoItem from "./TodoItem";
import Todo from "../models/todos";
import classes from "./Todos.module.css";

const Todos: React.FC<{ items: Todo[]; onRemoveTodo: (id: string) => void }> = (
  props
) => {
  return (
    <ul className ={classes.todos}>
      {props.items.map((item) => (
        <TodoItem
          key={item.id}
          text={item.text}
          onRemoveTodo={props.onRemoveTodo.bind(null, item.id)}
        />
      ))}
    </ul>
  );
};

export default Todos;

 

 

import classes from './TodoItem.module.css';


const TodoItem: React.FC<{text: string; onRemoveTodo: (event: React.MouseEvent) => void }> = (props) => {
    return <li className={classes.item} onClick={props.onRemoveTodo}>{props.text}</li>
};

export default TodoItem;