简体   繁体   English

反应测试中的 Linting 错误

[英]Linting errors in react testing

I am running some tests on a custom hook and the tests are working fine, although I'm getting a lot of errors under my localStorage, TEST_VALUE.我正在自定义挂钩上运行一些测试并且测试工作正常,尽管我在我的 localStorage TEST_VALUE 下遇到了很多错误。 Under localStorage I receive the following:在 localStorage 下,我收到以下信息:

Argument of type 'string | null' is not assignable to parameter of type 'string'.
  Type 'null' is not assignable to type 'string'.ts(2345)

I'm sure it is coming from my hook:我确定它来自我的钩子:

import { useState, useEffect } from 'react';

export const useStateWithLocalStorage = (defaultValue: string, key: string) => {
  const [value, setValue] = useState(() => {
    const storedValues = localStorage.getItem(key);

    return storedValues !== null ? JSON.parse(storedValues) : defaultValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
};

But don't know how I would get around it as !== null needs to be in the return for the function to work.但是不知道我将如何解决它,因为 !== null 需要在返回中才能使函数正常工作。

Here is my test file:这是我的测试文件:

import { renderHook, act } from '@testing-library/react';
import { useStateWithLocalStorage } from '../UseStateWithLocalStorage';

describe('Test local storage', () => {
  test('should set local storage with default value', () => {
    const TEST_KEY: string = 'form';
    const TEST_VALUE = { name: 'matt' };
    renderHook(() => useStateWithLocalStorage(TEST_VALUE, TEST_KEY));

//^^ ERROR HERE UNDER TEST_VALUE Argument of type '{ name: string; //^^ ERROR HERE UNDER TEST_VALUE 类型参数 '{ name: string; }' is not assignable to parameter of type 'string'. }' 不可分配给“字符串”类型的参数。

expect(JSON.parse(localStorage.getItem(TEST_KEY))).toEqual(TEST_VALUE);
      });

//^^ERROR HERE UNDER (localStorage.getItem(TEST_KEY) Argument of type 'string | null' is not assignable to parameter of type 'string'. Type 'null' is not assignable to type 'string'.ts //^^ERROR HERE UNDER (localStorage.getItem(TEST_KEY) 'string | null' 类型的参数不可分配给'string' 类型的参数。'null' 类型不可分配给'string'.ts

      test('should update localStorage when state changes', () => {
        const TEST_KEY: string | null = 'form';
        const TEST_VALUE = { name: 'bill' };
    
        const { result } = renderHook(() => useStateWithLocalStorage(TEST_VALUE, TEST_KEY));
    
        // Pulls from result.current to update state
        const [, setValue] = result.current;
        const newValue = { name: 'john' };
    
        act(() => {
          setValue(newValue);
        });
    
        expect(JSON.parse(localStorage.getItem(TEST_KEY))).toEqual(newValue);
      });
    });

Am I missing a type somewhere?我在某处缺少类型吗?

Second error第二个错误

The second one is easier, so lets start there.第二个更容易,所以让我们从那里开始。

localStorage.getItem is typed as: localStorage.getItem键入为:

Storage.getItem(key: string): string | null

Which means it accepts a string argument, but you pass it string | null这意味着它接受一个string参数,但你将它传递给string | null string | null

const TEST_KEY: string | null = 'form';
JSON.parse(localStorage.getItem(TEST_KEY))

That's what this error means:这就是这个错误的含义:

Argument of type 'string | 'string | 类型的参数null' is not assignable to parameter of type 'string'. null' 不能分配给“字符串”类型的参数。

Type 'null' is not assignable to type 'string'.(2345)类型“null”不可分配给类型“字符串”。(2345)

In this case you want to remove the type annotation for TEST_KEY which will make it typed as just string .在这种情况下,您要删除TEST_KEY的类型注释,这将使其键入为string

But then getItem returns string | null但随后getItem返回string | null string | null and JSON.parse accepts a string and can't handle null . string | nullJSON.parse接受一个string并且不能处理null So you have a similar problem.所以你有一个类似的问题。

You need to guard against that, too.你也需要提防这种情况。 But given that this is just a test, you don't have to provide a valid JSON string, since it will probably never even execute.但鉴于这只是一个测试,您不必提供有效的 JSON 字符串,因为它可能永远不会执行。

This means you could rewrite the above snippet to something like:这意味着您可以将上面的代码段重写为:

const TEST_KEY = 'form';
JSON.parse(localStorage.getItem(TEST_KEY) ?? 'error')

Or could also use a postfix !或者也可以使用后缀! to assert that the value is non null, but I don't recommend you use that because it's a bad habit. 断言该值不为空,但我不建议您使用它,因为这是一个坏习惯。

const TEST_KEY = 'form';
JSON.parse(localStorage.getItem(TEST_KEY)!)

First error第一个错误

You then type the first argument of your hook as a string in:然后,您将钩子的第一个参数作为string键入:

export const useStateWithLocalStorage = (defaultValue: string, key: string) => {

Then you pass it an object:然后你传递一个对象:

const TEST_VALUE = { name: 'matt' };
renderHook(() => useStateWithLocalStorage(TEST_VALUE, TEST_KEY));

That's what this error means:这就是这个错误的含义:

Argument of type '{ name: string; '{ name: string; 类型的参数}' is not assignable to parameter of type 'string'.(2345) }' 不可分配给“字符串”类型的参数。(2345)

To fix that, you must type useStateWithLocalStorage correctly.要解决此问题,您必须正确键入useStateWithLocalStorage It seems you expect to able to pass complex objects to useStateWithLocalStorage not just strings, so we need to change the type of the function argument.您似乎希望能够将复杂对象传递给useStateWithLocalStorage而不仅仅是字符串,因此我们需要更改函数参数的类型。

But also, you want strong type safety for whatever the state type is.而且,无论状态类型是什么,您都需要强大的类型安全性。 You could make that argument type any or unknown , but then you don't have strong type safety between input and output.您可以将该参数类型设置为anyunknown ,但是您在输入和输出之间没有强大的类型安全性。 So to do this right, I believe you need to make the function generic .所以要做到这一点,我相信你需要使函数generic

export const useStateWithLocalStorage = <T>(defaultValue: T, key: string) => {
  const [value, setValue] = useState<T>(() => {
    const storedValues = localStorage.getItem(key);

    return storedValues !== null ? JSON.parse(storedValues) : defaultValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
};

Now defaultValue can be any unknown type, which is remember as T .现在defaultValue可以是任何未知类型,记住为T We then pass that type to useState to make that state the same type as defaultValue .然后我们将该类型传递给useState以使该状态与defaultValue类型相同。 And now your function will return [T, Dispatch<SetStateAction<T>>] which gives you a strongly typed return value.现在您的函数将返回[T, Dispatch<SetStateAction<T>>] ,它为您提供强类型的返回值。


See playground 看游乐场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 defineEmits 的 Vue linting 错误 function - Vue linting errors for defineEmits function 使用ESlint整理React + Typescript项目 - Linting React+Typescript project with ESlint 如何使用React的setState()修复掉毛错误 - How to fix linting error with React's setState() 如何在没有 linting 错误的情况下配置角度项目 tsconfig paths[]? - how to configure an angular project tsconfig paths[] without linting errors? VS Code + TypeScript + ESLint:如何让 linting 错误不如编译器错误那么突出? - VS Code + TypeScript + ESLint: How can I make linting errors less prominent than compiler errors? Typescript 错误:扩展推断类型可防止 TS Linting 错误(提供了 Playground 示例) - Typescript Bug: Extending An Inferred Type Prevents TS Linting Errors (Playground Example Provided) 使用 TypeScript 设置时,Vue 3 模板中的 ref() 出现掉毛错误<setup lang="ts" script></setup> - Linting errors for ref()'s within Vue 3 templates when using setup with TypeScript <setup lang="ts" script> 订阅后Angular 5单元测试中的测试错误 - Testing errors in Angular 5 Unit Testing after subscribtion Typescript 中的 React 测试库 - React testing library in Typescript 使用 Typescript 进行反应测试 - React Testing with Typescript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM