Curso de React | Typescript en React

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.

Documentación oficial

Permite añadir tipos de datos a nuestras variables y constantes.

Un fichero que use typescript debe tener extensión ts. Si es un componente, debe tener extensión tsx.

Añadir Typescript a un proyecto de Vite existente

npm i typescript @types/react @types/react-dom @types/node

./tsconfig.json

{
  "display": "Default",
  "compilerOptions": {
    "baseUrl": "./src",
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "bundler",
    "target": "ESNext",
    "module": "ESNext",
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "lib": ["ES2015", "DOM"],
    "composite": false,
    "declaration": true,
    "declarationMap": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "inlineSources": false,
    "resolveJsonModule": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "preserveWatchOutput": true,
    "skipLibCheck": true,
    "strict": true
  },
  "include": ["./**/*.ts", "./**/*.tsx", "vite.config.js"],
  "exclude": ["dist", "build", "node_modules"]
}

./src/vite-env.d.ts

/// <reference types="vite/client" />

Declaración de tipos

Tipado básico

let n: number;
let txt: string;
let booleano: boolean;
let myDate: Date;
let arr: Array<number>;

enum Color { Red, Green, Blue };
let color: Color = Color.Green;

Funciones

 function a(num: number, text: string): string {
    return '';
 }

Trabajo con indefinidos

let edad : number | undefined

Funciones que pueden recibir indefinidos:

const hacerCosas = (libro: Libro | undefined) => 

o

const hacerCosas = (libro?: Libro) => 

Tipos

Aunque podemos declararlos en el propio fichero donde los usemos, es recomendable declararlos en módulo dedicado a la descripción del dominio (en nuestro caso common/types/Classroom.ts ).

export type Human = {
  id?: number; // Esto hará esta prop opcional
  name: string;
  age: number;
  height?:number; // Al poner la interrogación esta propiedad será opcional
  gender: string | null; // Al poner null, este valor aceptará valores nulos
  children: Human[];
}

A parte de Vanilla.js

A tener en cuenta en React:

Estados:

const [userId, setUserId] = useState<string>(null);

Props:

const BookC = ({ book, renderBooks, children }: { book: Book, renderBooks: () => void, children:React.ReactNode }) => {

Los ficheros ts tendrán código typescript, mientras que los ficheros tsx tendrán código typescript y jsx.

Context API:

type UserContext = [string | null, Dispatch<SetStateAction<string | null>>];

export const AppContext = createContext<UserContext | null>(null); 

export const useUserIdContext = () => useContext(AppContext);

const UserIdProvider = ({ children }: { children: ReactNode }) => {
  const [userId, setUserId] = useState<string | null>(null); 
  return (
    <AppContext.Provider value={[userId, setUserId]}>
      {children}
    </AppContext.Provider>
  );
};

export default UserIdProvider;

Trabajando con Firebase

import {
  ...,
  type QuerySnapshot
} from "firebase/firestore";

export const getTasks = async (studentId:string):Promise<Task[]> => {
  const colRef = collection(db, "students", studentId, "tasks");
  const result = await getDocs(query(colRef));
  return getArrayFromCollection<Task>(result);
};

const getArrayFromCollection = <T = { id: string; [key: string]: unknown }>(collection: QuerySnapshot): T[] => {
  return collection.docs.map((doc) => {
    return { ...doc.data(), id: doc.id } as T;
  });
};

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.