[TypeScript] 將TypeScript 導入到React專案的常見問題- createRoot參數錯誤

施慶銓
5 min readApr 20, 2023

--

在上一篇文章[TypeScript] 將TypeScript 導入到React專案- 起手式 ,記錄在React 專案中如何設定TypeScript開發環境、簡單介紹TypeScrip以及導入TypeScript的原因

接下來是將導入TypeScript 導入React 專案後遇到的問題

將rootElement 當作createRoot參數時發生錯誤

原因是, 在還沒將TypeScript 加入React App 時, 如果是透過CRA 建立的React App, 預設的src/index.js 內容大概是

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

而其中的getElementById預設回傳的類別為 HTMLElement null,

ReactDOM.createRoot 接收的第一個參數類型是Element 或是 DocumentFragment

其中getElementById 所回傳的類型中, null , 不是ReactDOM.createRoot 可以接受的類型

以至於導致下方的錯誤

類型 'HTMLElement | null' 的引數不可指派給類型 'Element | DocumentFragment' 的參數。
類型 'null' 不可指派給類型 'Element | DocumentFragment'。

要解決的方式有兩種.

  1. 型別斷言(Type Assertion)
  2. Null型別的處理

型別斷言(Type Assertion)

型別斷言(Type Assertion)是為了當TypeScript 無法推斷變數的型別時, 透過型別斷言, 直接指定變數的型別

若改寫上方的例子, 則可以變成

const rootElement = document.getElementById('root') as HTMLElement
const root = ReactDOM.createRoot(rootElement);

透過as 來指定rootElement 的型別就是HTMLElement

這樣當rootElement傳入ReactDOM.createRoot時, TypeScript只會將rootElement 判斷成HTMLElement , 也就不會報錯

Null型別的處理

其實就是跟我們一般在寫JavaScript 時, 通常為了避免在賦值給變數時, 我們以為有正確拿到值, 但實際上是null, 而導致意外使用null呼叫物件或其他型別的屬性.

一般這種狀況我們通常會用if(xxx === null) 來先做預處理

而這個問題也可以用這樣方式處理, 例如

const rootElement = document.getElementById('root')
if(!rootElement) {
throw new Error('Failed to find the root element');
}
const root = ReactDOM.createRoot(rootElement);

當加入rootElementnull時要如何處理邏輯後, TypeScript 就會將rootElement 的型別視為HTMLElement (因為rootElement只會有nullHTMLElement 兩種可能的型別)

這樣ReactDOM.createRoot也理所當然不會有任何問題

--

--

施慶銓
施慶銓

No responses yet