[英]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?我在某处缺少类型吗?
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 | null
和JSON.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)!)
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.您可以将该参数类型设置为
any
或unknown
,但是您在输入和输出之间没有强大的类型安全性。 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>>]
,它为您提供强类型的返回值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.