在typeScript中使用useRef的问题

时间:2020-07-27 16:48:07

标签: javascript reactjs typescript

我有以下代码;

App.tsx

export default function App() {
  const [canvasRef, canvasWidth, canvasHeight] = useCanvas();
  return (
    <div>
      <canvas
        ref={canvasRef}
      />
    </div>
  )
}

useCanvas.ts

import { useRef, useEffect } from "react";

const canvasWidth = 1200;
const canvasHeight = 600;

export default function useCanvas() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  return [canvasRef, canvasWidth, canvasHeight]
}

是的,这正是我在代码中所拥有的,但是,我从Vscode收到App.tsx中的以下错误;

(JSX attribute) React.ClassAttributes<HTMLCanvasElement>.ref?: string | React.RefObject<HTMLCanvasElement> | ((instance: HTMLCanvasElement | null) => void) | null | undefined
Type 'number | RefObject<HTMLCanvasElement>' is not assignable to type 'string | RefObject<HTMLCanvasElement> | ((instance: HTMLCanvasElement | null) => void) | null | undefined'.
  Type 'number' is not assignable to type 'string | RefObject<HTMLCanvasElement> | ((instance: HTMLCanvasElement | null) => void) | null | undefined'.ts(2322)
index.d.ts(143, 9): The expected type comes from property 'ref' which is declared here on type 'DetailedHTMLProps<CanvasHTMLAttributes<HTMLCanvasElement>, HTMLCanvasElement>'

任何建议将不胜感激。

2 个答案:

答案 0 :(得分:0)

function useCanvas() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  return [canvasRef, canvasWidth, canvasHeight]
}

由于您没有给返回值指定类型,因此typescript会推断出它。在推断数组的类型时,打字稿将假定它是普通数组,而不是tuple

为简化起见,假设您要返回此代码:

function () {
  return [1, 'a'];
}

Typescript将推断类型为(number | string)[]。换句话说,是任意长度的数组,其中每个元素可以是字符串的数量。它不会推断类型为[number, string]。因此,如果您尝试与该数组的索引0进行交互,则打字稿将无法告诉您这绝对是一个数字,只能告诉您它是一个数字或字符串。

因此,您的第一个选择是为要返回的内容提供显式类型。在我的简化情况下,它将是:

function () {
  const result: [number, string] = [1, 'a'];
  return result;
}

// or
function (): [number, string] {
  return [1, 'a'];
}

// or
function () {
  return [1, 'a'] as [number, string];
}

我不确定代码类型是否正确,但是您可以检查变量并找出答案。

另一种选择,也许是更简单的选择,是使用as const来帮助打字稿推断类型。 as const告诉我们这将永远不会改变,因此它将把它视为一个元组而不是一个数组。

function useCanvas() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  return [canvasRef, canvasWidth, canvasHeight] as const;
}

答案 1 :(得分:0)

自定义钩子的返回类型为(number | React.MutableRefObject<HTMLCanvasElement>)[],因为typescript推断它返回了包含这些类型的数组。这就是为什么您无法正确键入App.tsx中解构的变量的原因(如果将其悬停,它们将全部属于number | React.MutableRefObject<HTMLCanvasElement>类型。)

您需要使用一个元组来准确告诉打字稿此数组中包含的内容。

您可以像这样将键入信息添加到自定义钩子中:

import { useRef, useEffect, MutableRefObject } from "react";

const canvasWidth = 1200;
const canvasHeight = 600;

export default function useCanvas(): [MutableRefObject<HTMLCanvasElement>, number, number] {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  return [canvasRef, canvasWidth, canvasHeight]
}