개발 일기

2024-12-09(타입스크립트)

민ズl 2024. 12. 9. 18:30

낙관적업데이트

const { mutate: handleLike } = useMutation({
    mutationFn: ({ id, currentLiked }) => // 인자는 한개, 여러개일땐 객체로!
      todoApi.patch(`/todos/${id}`, { liked: !currentLiked }),
    onMutate: async ({ id, currentLiked }) => {
      await queryClient.cancelQueries({ queryKey: ["todos"] }); // onMutate쓸때 제일 먼저 작성!

      const previousTodos = queryClient.getQueryData(["todos"]); // 백업느낌!
      queryClient.setQueryData(["todos"], (prev) => //setState같음!
        prev.map((todo) =>
          todo.id === id ? { ...todo, liked: !currentLiked } : todo
        )
      );
      return { previousTodos };
    },
    
    onError: (err, _, context) => {
    //상태 바꾸기: queryClient.setQueryData
      queryClient.setQueryData(["todos"], () => context.previousTodos);
    },
    
    //항상 실행되는 부분(DB의 데이터와 UI 데이터를 동기화)
    onSettled: () => {
      queryClient.invalidateQueries({queryKey: ["todos"]});
    },
  });

 

typescript

  • 자바스크립트의 superset
    (*superset : 상위 집합)
  • 장점
    • 자바스크립트보다 신뢰할 수 있는 코드 : by 타입체크 , 코드의 예측 가능성을 높임
    • 규모 확장성 : 코드베이스가 커질수록 타입 시스템덕분에 안전하고 효율적으로 관리가능
    • 개발 도구 지원 : 강력한 코드 자동 완성을 지원하여 생산성을 높임
  • 실시간 개발환경에서 타입 체크가 동작
    (따로 패키지매니저등 설치안해도 .ts파일에서 타입 체크가 작동, 단 기본작동만 함 ex : any불가)
  • tsconfig.json : 타입 체크, ts 패키지가 설치되어 있어야 함

원시타입

const name: string = "kim'

*타입 어노테이션(: string) : 마치 가드같이, 지정한 타입아니면 못들여보냄

 

any

권장하지 않음, 임시로 사용할때 사용

 

unknown

어떤 타입인지 모를때, 런타임에 타입 검사해야 사용 가능, if문일때

const unknownValue: unknown = 42;
if(typeof unknownValue === 'number') {
   console.log(unknownValue + 1);
}

 

리터럴타입

특정한 값만을 허용하는 타입

const dataOnly10: 10 = 10;

 

인터섹션 타입

모든 타입의 조건을 동시에 만족하는 타입(마치 교집합)

type RedOrBlue = 'red' | 'blue'

 

배열타입

  • Array<number> :  잘안씀
  • number[] : 

튜플타입

각 요소에 대해 정확한 타입과 순서를 지정 (요소 개수 제한됨)

const tupleArr: [string, number] = ["123", 123];

 

유니온타입

각 요소가 여러 가지 타입 중 하나일 수 있음을 나타냄

const unionArr: (string | number)[] = [123, "123", 123, 123, "123"];

 

타입추론

코드에서 명시적으로 타입을 지정하지 않아도 자동으로 추론

 

객체 타입

  • type alias
  • 주로 사용
const student: {name:string; age: number; isStudent: boolean} = {
  name: "Jane",
  age: 22,
  isStudent: true,
};

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

 

interface

  • 클래스일때 주로 사용
//interface
interface Person {
  name: "Jane",
  age: 22,
  isStudent: true,
}

const student: Person = {
  name: "Jane",
  age: 22,
  isStudent: true,
};

 

중첩 객체 타입

type Address = {
  street: string;
  city: string;
  country: string;
};

type PersonWithAddress = Person & {
  address: Address;
};

const studentWithAddress: PersonWithAddress = {
  name: "John",
  age: 24,
  isStudent: false,
  address: {
    street: "123 Main St",
    city: "Anytown",
    country: "USA",
  },
};

 

옵셔널

  • ?붙이기
  • 해당 속성이 존재하지 않아도 오류가 발생하지 않도록 할 수 있음
type PersonWithAddress = Person & {
   address?: Address;
};

const studentWithAddress: PersonWithAddress = {
  name: "John",
  age: 24,
  isStudent: false,
  address: {
    street: "123 Main St",
    city: "Anytown",
    country: "USA",
  },
};

 

함수 타입

인자값, 리턴값에 대한 타입 지정

function greet(name: string): string {
  return `Hello, ${name}!`;
}

 

void

  • return값은 없음,
  • js에선 return이 없으면 undefined가 리턴이 됨
function printName(name: string): void {
  console.log(name);
}

 

그럼 만약 반환값이 undefined일땐🤔

function printName(name: string): void { 
  console.log(name);
  return undefined;
}

 

화살표함수로는

const logMessage1 = (message: string): void => {
  console.log(message);
};
// 또는
const logMessage2: (message: string) => void = (message) => {
  console.log(message);
};

 

* call signature

// 또는
type LogMessageType = (message: string) => void;
const logMessage3: LogMessageType = (message) => {
  console.log(message);
};

 

Type Assertion

! 는 non-null assertion 으로 null 타입이 아님을 의미

! 대신 as 키워드로도 타입단언이 가능

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
);

 

우선순위

const [isLoading, setIsLoading] = useState<boolean>(true); // 우선순위 1<boolean> 2(true)

 

const [error , setError] = useState<null | Error>(null); // setError(null);

try {
   ...
} catch (err) {
   if (err instanceof Error) {
      setError(err)
   }else {
      setError(new Error(`알 수 없는 에러 발생: ${err}`));
   }
}
import {type Todo} from '...';

 

이벤트 타입에서 타입 지정

1. e 써보고 마우스 올려두기

2. 온체인지에 마우스 올려두기

 

 

map돌릴때 콜백엔 타입지정 하지 않긔

{todos.map((todo) => (
    <li
      key={todo.id}
      style={{
        border: "1px solid black",
        padding: "10px",
        marginBottom: "10px",
        textDecoration: todo.isDone ? "line-through" : "none",
      }}
    >
    ...

 

인덱스 접근 타입 (indexed access type)

객체 타입의 특정 속성 타입을 쉽게 가져올 수 있음

//
export type Todo = {
  id: string;
  title: string;
  contents: string;
  createdAt: number;
  extraProperty?: ExtraPropertyType;
};

export type TodoWithIsDone = Todo & {
  isDone: boolean;
};


//
...
 const toggleTodo = (id: TodoWithIsDone["id"]) => {
    setTodos((prevTodos) =>
      prevTodos.map((todo) =>
        todo.id === id ? { ...todo, isDone: !todo.isDone } : todo,
      ),
    );
};