TypeScript'i kullanma

TypeScript, JavaScript kod tabanlarına tür tanımları eklemenin popüler bir yoludur. TypeScript,kullanıma hazır olarak JSX’i destekler ve projenize @types/react ve @types/react-dom ekleyerek tam React Web desteği alabilirsiniz.

Kurulum

Tüm canlı ortam düzeyinde React framework’leri TypeScript kullanımı için destek sunar. Kurulum için framework’e özgü kılavuzu takip edin:

Mevcut Bir React Projesine TypeScript Ekleme

React’in tür tanımlamalarının en son sürümünü yüklemek için:

Terminal
npm install @types/react @types/react-dom

tsconfig.json dosyanızda aşağıdaki derleyici seçeneklerinin ayarlanması gerekir::

  1. dom, lib’e dahil edilmelidir (Not: Eğer lib seçeneği belirtilmemişse, dom varsayılan olarak dahil edilir).
  2. jsx geçerli seçeneklerden birine ayarlanmalıdır. Çoğu uygulama için preserve yeterli olacaktır. Eğer bir kütüphane yayımlıyorsanız, hangi değeri seçeceğiniz konusunda If you’re publishing a library, consult the jsx documentation başvurun.

React Bileşenleri ile TypeScript

Not

JSX içeren her dosya tsx dosya uzantısını kullanmalıdır. Bu, TypeScript’e bu dosyanın JSX içerdiğini belirten TypeScript’e özel bir uzantıdır.

React ile TypeScript yazmak, React ile JavaScript yazmaya çok benzer. Bir bileşenle çalışırken ana fark, bileşenin props’ları için türler sağlayabilmenizdir. Bu türler, doğruluk kontrolü yapmak ve editörlerde yerinde dokümantasyon sağlamak için kullanılabilir

Hızlı Başlangıç kılavuzundan MyButton bileşenini alarak, butonun title’ını tanımlayan bir tür ekleyebiliriz:

function MyButton({ title }: { title: string }) {
  return (
    <button>{title}</button>
  );
}

export default function MyApp() {
  return (
    <div>
      <h1>Uygulamama hoş geldiniz</h1>
      <MyButton title="Ben bir butonum" />
    </div>
  );
}

Not

Bu sandboxes TypeScript kodunu çalıştırabilir, ancak tür denetleyicisini çalıştırmaz. Bu, TypeScript sandboxes öğrenmek için değiştirebileceğiniz, ancak tür hataları veya uyarıları almayacağınız anlamına gelir. Tür denetimi almak için TypeScript Playground kullanabilir veya daha tam özellikli bir çevrimiçi sandbox kullanabilirsiniz.

Bu yerinde sözdizimi, bir bileşen için türler sağlamanın en basit yoludur; ancak birkaç alan tanımlamaya başladığınızda karmaşık hale gelebilir. Bunun yerine, bileşenin props’larını tanımlamak için bir interface veya type kullanabilirsiniz:

interface MyButtonProps {
  /** Butonun içinde görüntülenecek metin */
  title: string;
  /** Butonun etkileşime girilip girilemeyeceği */
  disabled: boolean;
}

function MyButton({ title, disabled }: MyButtonProps) {
  return (
    <button disabled={disabled}>{title}</button>
  );
}

export default function MyApp() {
  return (
    <div>
      <h1>Uygulamama hoş geldiniz</h1>
      <MyButton title="Ben devre dışı bırakılmış bir butonum" disabled={true}/>
    </div>
  );
}

Bileşeninizin props’larını tanımlayan tür, ihtiyaç duyduğunuz kadar basit veya karmaşık olabilir; ancak bunlar ya type ya da interface ile tanımlanmış bir nesne türü olmalıdır. TypeScript’in nesneleri nasıl tanımladığını Nesne Türleri bölümünde öğrenebilirsiniz, ayrıca birkaç farklı türden birini alabilen bir prop tanımlamak için Birleşim Türleri kullanmayı ve daha karmaşık kullanım senaryoları için Türlerden Türler Oluşturma kılavuzunu incelemeyi de düşünebilirsiniz.

Örnek Hooklar

@types/react’den gelen tür tanımlamaları, yerleşik Hooks için türleri içerir, böylece bileşenlerinizde ek bir ayar yapmadan kullanabilirsiniz. Bu türler, bileşeninizde yazdığınız kodu dikkate alacak şekilde tasarlanmıştır, bu nedenle çoğu zaman çıkarılan türleralırsınız ve ideal olarak türleri sağlama detaylarıyla ilgilenmeniz gerekmez.

Ancak,Hooklar için tipleri nasıl sağlayacağımıza dair birkaç örneğe bakabiliriz.

useState

useState Hook’udeğerinin tipini belirlemek için başlangıç durumu olarak geçirilen değeri yeniden kullanacaktır. Örneğin:

// Infer the type as "boolean"
const [enabled, setEnabled] = useState(false);

Bu, enabled değişkenine boolean tipini atayacak ve setEnabled fonksiyonu ya bir boolean argümanı ya da bir boolean döndüren bir fonksiyon alacaktır. Eğer duruma açıkça bir tip sağlamak istiyorsanız, bunu useState çağrısına bir tip argümanı vererek yapabilirsiniz:

// Tipi açıkça "boolean" olarak ayarlayın
const [enabled, setEnabled] = useState<boolean>(false);

Bu durumda çok faydalı değil, ancak bir tip sağlamanız gereken yaygın bir durum, bir birleşim tipiyle karşılaştığınızda ortaya çıkar. Örneğin, burada status birkaç farklı string değerinden biri olabilir

type Status = "idle" | "loading" | "success" | "error";

const [status, setStatus] = useState<Status>("idle");

Ya da, Durum yapılandırma ilkeleri bölümünde önerildiği gibi, ilgili durumu bir nesne olarak gruplandırabilir ve farklı olasılıkları nesne tipleri aracılığıyla tanımlayabilirsiniz:

type RequestState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success', data: any }
| { status: 'error', error: Error };

const [requestState, setRequestState] = useState<RequestState>({ status: 'idle' });

useReducer

useReducer Hook’u, bir azaltıcı fonksiyon ve bir başlangıç durumu alan daha karmaşık bir Hook’tur. Azaltıcı fonksiyonun tipleri, başlangıç durumundan çıkarılır. useReducer çağrısına bir tip argümanı sağlayarak duruma bir tip verebilirsiniz, ancak genellikle tipi başlangıç durumuna ayarlamak daha iyidir:

import {useReducer} from 'react';

interface State {
   count: number 
};

type CounterAction =
  | { type: "reset" }
  | { type: "setCount"; value: State["count"] }

const initialState: State = { count: 0 };

function stateReducer(state: State, action: CounterAction): State {
  switch (action.type) {
    case "reset":
      return initialState;
    case "setCount":
      return { ...state, count: action.value };
    default:
      throw new Error("Unknown action");
  }
}

export default function App() {
  const [state, dispatch] = useReducer(stateReducer, initialState);

  const addFive = () => dispatch({ type: "setCount", value: state.count + 5 });
  const reset = () => dispatch({ type: "reset" });

  return (
    <div>
      <h1>Sayacıma hoş geldiniz</h1>

      <p>Sayaç: {state.count}</p>
      <button onClick={addFive}>5 Ekle</button>
      <button onClick={reset}>Sıfırla</button>
    </div>
  );
}

TypeScript’i birkaç önemli yerde kullanıyoruz:

  • interface State reducer’ın durumunun yapısını tanımlar.
  • type CounterAction reducer’a gönderilebilecek farklı eylemleri tanımlar.
  • const initialState: State başlangıç durumu için bir tür sağlar ve ayrıca varsayılan olarak useReducer tarafından kullanılan türdür.
  • stateReducer(state: State, action: CounterAction): State reducer fonksiyonunun argümanları ve dönüş değeri için türleri belirler.

initialState’e tür ayarlamanın daha açık bir alternatifi, useReducer’a bir tür argümanı sağlamaktır:

import { stateReducer, State } from './your-reducer-implementation';

const initialState = { count: 0 };

export default function App() {
const [state, dispatch] = useReducer<State>(stateReducer, initialState);
}

useContext

useContext Hook’uverileri bileşen ağacında aşağıya doğru geçirebilmenin bir tekniğidir ve bu işlem için bileşenler üzerinden props geçirmeye gerek kalmaz. Bir sağlayıcı bileşeni oluşturarak ve genellikle bir alt bileşende değeri tüketmek için bir Hook oluşturarak kullanılır.

Context tarafından sağlanan değerin türü, createContext çağrısına geçirilen değerden çıkarılır:

import { createContext, useContext, useState } from 'react';

type Theme = "light" | "dark" | "system";
const ThemeContext = createContext<Theme>("system");

const useGetTheme = () => useContext(ThemeContext);

export default function MyApp() {
  const [theme, setTheme] = useState<Theme>('light');

  return (
    <ThemeContext.Provider value={theme}>
      <MyComponent />
    </ThemeContext.Provider>
  )
}

function MyComponent() {
  const theme = useGetTheme();

  return (
    <div>
      <p>Güncel tema: {theme}</p>
    </div>
  )
}

Bu teknik, anlamlı bir varsayılan değeriniz olduğunda işe yarar; ancak bazen varsayılan değeriniz olmadığında null mantıklı gelebilir. Ancak, tür sisteminin kodunuzu anlaması için, createContext üzerinde açıkça ContextShape | null ayarlamanız gerekir.

Bu, bağlam tüketicileri için türde | nullu ortadan kaldırmanız gerektiği sorununu doğurur. Önerimiz, Hook’un varlığını çalışma zamanında kontrol etmesi ve mevcut değilse bir hata fırlatmasıdır:

import { createContext, useContext, useState, useMemo } from 'react';

// Bu daha basit bir örnek, ama burada daha karmaşık bir nesne hayal edebilirsiniz.
type ComplexObject = {
kind: string
};

// Context, varsayılan değeri doğru bir şekilde yansıtmak için türde `| null` ile oluşturulmuştur.
const Context = createContext<ComplexObject | null>(null);

// `| null` Hook’taki kontrol aracılığıyla kaldırılacaktır.
const useGetComplexObject = () => {
const object = useContext(Context);
if (!object) { throw new Error("useGetComplexObject must be used within a Provider") }
return object;
}

export default function MyApp() {
const object = useMemo(() => ({ kind: "complex" }), []);

return (
<Context.Provider value={object}>
<MyComponent />
</Context.Provider>
)
}

function MyComponent() {
const object = useGetComplexObject();

return (
<div>
<p>Mevcut nesne: {object.kind}</p>
</div>
)
}

useMemo

useMemo Hook’u, bir fonksiyon çağrısından hafızada tutulan bir değeri oluşturur veya yeniden erişir ve yalnızca ikinci parametre olarak geçirilen bağımlılıklar değiştiğinde fonksiyonu tekrar çalıştırır. Hook’un çağrılmasının sonucu, ilk parametredeki fonksiyondan dönen değerden çıkarılır. Hook’a bir tür argümanı sağlayarak daha açık olabilirsiniz.

// visibleTodos’un türü, filterTodos’un dönen değerinden çıkarılır.
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);

useCallback

useCallback ikinci parametre olarak geçirilen bağımlılıklar aynı olduğu sürece bir fonksiyona kararlı bir referans sağlar. useMemo gibi, fonksiyonun türü ilk parametredeki fonksiyondan dönen değerden çıkarılır ve Hook’a bir tür argümanı sağlayarak daha açık olabilirsiniz.

const handleClick = useCallback(() => {
// ...
}, [todos]);

TypeScript strict modunda çalışırken, useCallback kullanırken geri çağırma fonksiyonunuzun parametreleri için tür eklemeniz gerekir. Bunun nedeni, geri çağırma fonksiyonunun türünün dönen değerden çıkarılmasıdır ve parametreler olmadan tür tam olarak anlaşılamaz.

Kod stili tercihlerine bağlı olarak, geri çağırmayı tanımlarken aynı anda olay işleyici için tür sağlamak amacıyla React türlerinden *EventHandler fonksiyonlarını kullanabilirsiniz:

import { useState, useCallback } from 'react';

export default function Form() {
const [value, setValue] = useState("Change me");

const handleChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>((event) => {
setValue(event.currentTarget.value);
}, [setValue])

return (
<>
<input value={value} onChange={handleChange} />
<p>Value: {value}</p>
</>
);
}

Kullanışlı Türler

@types/react paketinden gelen oldukça geniş bir tür seti vardır ve React ile TypeScript’in nasıl etkileşime girdiğini anladığınızda incelemeye değer. Bunları DefinitelyTyped’teki React klasöründe. bulabilirsiniz. Burada daha yaygın kullanılan birkaç türü ele alacağız.

DOM Olayları

React’te DOM olaylarıyla çalışırken, olayın türü genellikle olay işleyicisinden çıkarılabilir. Ancak, bir fonksiyonu olay işleyicisine geçirmek üzere ayırmak istediğinizde, olayın türünü açıkça belirtmeniz gerekir.

import { useState } from 'react';

export default function Form() {
  const [value, setValue] = useState("Beni değiştir");

  function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
    setValue(event.currentTarget.value);
  }

  return (
    <>
      <input value={value} onChange={handleChange} />
      <p>Değer: {value}</p>
    </>
  );
}

React türlerinde birçok olay türü sağlanmıştır - tam listeye buradan ulaşabilirsiniz. Bu liste, DOM’daki en popüler olaylara.

Kullandığınız olay işleyici için türü belirlerken, ilk olarak olay işleyicinin üzerine geldiğinizde görünen bilgiye bakabilirsiniz; bu, olayın türünü gösterecektir.

Bu listede yer almayan bir olayı kullanmanız gerekirse, tüm olaylar için temel tür olan React.SyntheticEvent türünü kullanabilirsiniz.

Children

Bir bileşenin children prop’unu tanımlamak için iki yaygın yol vardır. İlki, JSX içinde children olarak geçebilecek tüm olası türlerin birleşimi olan React.ReactNode türünü kullanmaktır:

interface ModalRendererProps {
title: string;
children: React.ReactNode;
}

Bu, children için oldukça geniş bir tanımdır. İkinci yol ise, sadece JSX öğelerini ve JavaScript ilkel türleri (string veya number gibi) içermeyen React.ReactElement türünü kullanmaktır:

interface ModalRendererProps {
title: string;
children: React.ReactElement;
}

Dikkat edilmesi gereken bir nokta, TypeScript’i kullanarak children’ın belirli bir türdeki JSX öğeleri olduğunu tanımlayamayacağınızdır; bu nedenle yalnızca <li> children’ları kabul eden bir bileşeni tanımlamak için tür sistemini kullanamazsınız.

React.ReactNode ve React.ReactElement örneklerini tür denetleyicisi ile birlikte bu TypeScript playground(https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgIilQ3wChSB6CxYmAOmXRgDkIATJOdNJMGAZzgwAFpxAR+8YADswAVwGkZMJFEzpOjDKw4AFHGEEBvUnDhphwADZsi0gFw0mDWjqQBuUgF9yaCNMlENzgAXjgACjADfkctFnYkfQhDAEpQgD44AB42YAA3dKMo5P46C2tbJGkvLIpcgt9-QLi3AEEwMFCItJDMrPTTbIQ3dKywdIB5aU4kKyQQKpha8drhhIGzLLWODbNs3b3s8YAxKBQAcwXpAThMaGWDvbH0gFloGbmrgQfBzYpd1YjQZbEYARkB6zMwO2SHSAAlZlYIBCdtCRkZpHIrFYahQYQD8UYYFA5EhcfjyGYqHAXnJAsIUHlOOUbHYhMIIHJzsI0Qk4P9SLUBuRqXEXEwAKKfRZcNA8PiCfxWACecAAUgBlAAacFm80W-CU11U6h4TgwUv11yShjgJjMLMqDnN9Dilq+nh8pD8AXgCHdMrCkWisVoAet0R6fXqhWKhjKllZVVxMcavpd4Zg7U6Qaj+2hmdG4zeRF10uu-Aeq0LBfLMEe-V+T2L7zLVu+FBWLdLeq+lc7DYFf39deFVOotMCACNOCh1dq219a+30uC8YWoZsRyuEdjkevR8uvoVMdjyTWt4WiSSydXD4NqZP4AymeZE072ZzuUeZQKheQgA)’ında görebilirsiniz..

Stil Propları

React’ta inline stiller kullanırken, style prop’una geçirilen nesneyi tanımlamak için React.CSSProperties kullanabilirsiniz. Bu tür, tüm olası CSS özelliklerinin birleşimidir ve style prop’una geçerli CSS özellikleri sağladığınızdan emin olmak ve düzenleyicinizde otomatik tamamlama almak için iyi bir yoldur.

interface MyComponentProps {
style: React.CSSProperties;
}

Daha Fazla Öğrenme

Bu rehber, TypeScript’i React ile kullanmanın temellerini kapsadı, ancak öğrenilecek daha çok şey var. Dokümanlardaki bireysel API sayfaları, TypeScript ile nasıl kullanılacağına dair daha derinlemesine belgeler içerebilir.

Aşağıdaki kaynakları öneriyoruz: