Reactjs 打字脚本可以';不要告诉我';如果参数未定义,m将提前返回
我将TypeScript与React一起使用,我不明白为什么TS不能判断如果Reactjs 打字脚本可以';不要告诉我';如果参数未定义,m将提前返回,reactjs,typescript,react-hooks,Reactjs,Typescript,React Hooks,我将TypeScript与React一起使用,我不明白为什么TS不能判断如果previous是undefined,那么下面的钩子会提前返回。它抱怨previous.length(“对象可能未定义”),因为它认为previous可能是undefined,但情况并非如此,因为如果是这样,函数将提前返回 function ReactComponent() { const previous = usePrevious(value) React.useEffect(() =&
previous
是undefined
,那么下面的钩子会提前返回。它抱怨previous.length
(“对象可能未定义”),因为它认为previous可能是undefined
,但情况并非如此,因为如果是这样,函数将提前返回
function ReactComponent() {
const previous = usePrevious(value)
React.useEffect(() => {
if (previous === undefined) {
return
}
if (previous.length) { // TS says "Object is possibly undefined" despite the return gate above
}
}, [previous])
return null
}
奇怪的是,这只是React钩子中的一个问题。下面的代码不抱怨
const bar: Array<number> | undefined = undefined
function foo() {
if (bar === undefined) {
return
}
if (bar.length) { // TS does NOT complain here
}
}
我可以通过明确说明此函数的返回类型为any
来解决此问题。换句话说,通过将函数usePrevious(value:any){…}
更改为函数usePrevious(value:any):any{…}
为什么要修复它对我来说仍然是一个谜,所以我现在就把它打开。
usePrevious
有一个始终未定义的返回类型。尝试将其键入为:
function usePrevious<T>(value: T): T | undefined {
const ref = React.useRef<T>();
React.useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
函数usePrevious(值:T):T |未定义{
const ref=React.useRef();
React.useffect(()=>{
参考电流=值;
},[价值];
返回参考电流;
}
usePrevious
具有始终未定义的返回类型。尝试将其键入为:
function usePrevious<T>(value: T): T | undefined {
const ref = React.useRef<T>();
React.useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
函数usePrevious(值:T):T |未定义{
const ref=React.useRef();
React.useffect(()=>{
参考电流=值;
},[价值];
返回参考电流;
}
该死,这和我刚才写的@Federkun lol很相似
import { useRef, useEffect, MutableRefObject } from 'react';
type CustomNonNullable<T> = T extends null | undefined
? never
: T;
// if generic parameter <T> is a function Type, it extracts the return type
type ReturnTypeOf<T extends (...args: any) => any> = T extends (
...args: any
) => infer U
? U
: any;
export default function usePrevious<T, P>(
value: T,
previousValue: P
) {
const refMutable: MutableRefObject<T | undefined> = useRef<T>(); // refMutable: MutableRefObject<T | undefined>
const refPrevious: MutableRefObject<P | undefined> = useRef<P>(); // refInitial: RefObject<T>
// use nonullable ! operator to override refMutable.current conditionally undefined
const NonnullableValue: CustomNonNullable<T> = refMutable!.current! ?? value!;
const NonnullablePreviousValue: CustomNonNullable<P> = refPrevious!.current! ?? previousValue!;
useEffect(() => {
refMutable.current = value ?? undefined;
refPrevious.current = previousValue ?? undefined;
}, [value, previousValue]);
return { NonnullablePreviousValue, NonnullableValue };
}
let y: ReturnTypeOf<typeof usePrevious>;
/**
* @var y inferred
let y: {
NonnullablePreviousValue: unknown;
NonnullableValue: unknown;
}
*/
export const inferredYObject = () => {
const { NonnullablePreviousValue, NonnullableValue } = y;
const trulyPrivateObject = Object.freeze({
NonnullablePreviousValue,
NonnullableValue
} as const);
return trulyPrivateObject;
};
/**
* @function inferredYObject has the following type
*Readonly<{
readonly NonnullablePreviousValue: unknown;
readonly NonnullableValue: unknown;
}>
* this makes it safe at runtime -- prevents XSSmodification
*/
从'react'导入{useRef,useffect,MutableRefObject};
类型CustomNonNullable=T扩展null |未定义
? 从未
:T;
//如果泛型参数是函数类型,它将提取返回类型
类型ReturnTypeOf any>=T扩展(
…阿格斯:有吗
)=>推断U
? U
:任何;
导出默认函数usePrevious(
值:T,
先前值:P
) {
常量refMutable:MutableRefObject=useRef();//refMutable:MutableRefObject
const refPrevious:MutableRefObject=useRef
();//refInitial:RefObject
//使用nonullable!运算符重写refMutable.current有条件未定义
常量NonnullableValue:CustomNonNullable=refMutable!。current!?value!;
常量NonnullablePreviousValue:CustomNonNullable
=refPrevious!.current!?previousValue!;
useffect(()=>{
refMutable.current=值??未定义;
refPrevious.current=previousValue??未定义;
},[value,previousValue]);
返回{NonnullablePreviousValue,NonnullableValue};
}
让y:ReturnTypeOf;
/**
*@var y
让我来说说:{
NonnullablePreviousValue:未知;
非NullableValue:未知;
}
*/
导出常量推断对象=()=>{
常量{NonnullablePreviousValue,NonnullableValue}=y;
const trulyprovateobject=Object.freeze({
不可为空的PreviousValue,
非空值
}作为常量);
返回真正私有的对象;
};
/**
*@function inferredYObject具有以下类型
*只读
*这使得它在运行时安全—防止XSM修改
*/
该死,这和我刚才写的@Federkun lol很相似
import { useRef, useEffect, MutableRefObject } from 'react';
type CustomNonNullable<T> = T extends null | undefined
? never
: T;
// if generic parameter <T> is a function Type, it extracts the return type
type ReturnTypeOf<T extends (...args: any) => any> = T extends (
...args: any
) => infer U
? U
: any;
export default function usePrevious<T, P>(
value: T,
previousValue: P
) {
const refMutable: MutableRefObject<T | undefined> = useRef<T>(); // refMutable: MutableRefObject<T | undefined>
const refPrevious: MutableRefObject<P | undefined> = useRef<P>(); // refInitial: RefObject<T>
// use nonullable ! operator to override refMutable.current conditionally undefined
const NonnullableValue: CustomNonNullable<T> = refMutable!.current! ?? value!;
const NonnullablePreviousValue: CustomNonNullable<P> = refPrevious!.current! ?? previousValue!;
useEffect(() => {
refMutable.current = value ?? undefined;
refPrevious.current = previousValue ?? undefined;
}, [value, previousValue]);
return { NonnullablePreviousValue, NonnullableValue };
}
let y: ReturnTypeOf<typeof usePrevious>;
/**
* @var y inferred
let y: {
NonnullablePreviousValue: unknown;
NonnullableValue: unknown;
}
*/
export const inferredYObject = () => {
const { NonnullablePreviousValue, NonnullableValue } = y;
const trulyPrivateObject = Object.freeze({
NonnullablePreviousValue,
NonnullableValue
} as const);
return trulyPrivateObject;
};
/**
* @function inferredYObject has the following type
*Readonly<{
readonly NonnullablePreviousValue: unknown;
readonly NonnullableValue: unknown;
}>
* this makes it safe at runtime -- prevents XSSmodification
*/
从'react'导入{useRef,useffect,MutableRefObject};
类型CustomNonNullable=T扩展null |未定义
? 从未
:T;
//如果泛型参数是函数类型,它将提取返回类型
类型ReturnTypeOf any>=T扩展(
…阿格斯:有吗
)=>推断U
? U
:任何;
导出默认函数usePrevious(
值:T,
先前值:P
) {
常量refMutable:MutableRefObject=useRef();//refMutable:MutableRefObject
const refPrevious:MutableRefObject=useRef
();//refInitial:RefObject
//使用nonullable!运算符重写refMutable.current有条件未定义
常量NonnullableValue:CustomNonNullable=refMutable!。current!?value!;
常量NonnullablePreviousValue:CustomNonNullable
=refPrevious!.current!?previousValue!;
useffect(()=>{
refMutable.current=值??未定义;
refPrevious.current=previousValue??未定义;
},[value,previousValue]);
返回{NonnullablePreviousValue,NonnullableValue};
}
让y:ReturnTypeOf;
/**
*@var y
让我来说说:{
NonnullablePreviousValue:未知;
非NullableValue:未知;
}
*/
导出常量推断对象=()=>{
常量{NonnullablePreviousValue,NonnullableValue}=y;
const trulyprovateobject=Object.freeze({
不可为空的PreviousValue,
非空值
}作为常量);
返回真正私有的对象;
};
/**
*@function inferredYObject具有以下类型
*只读
*这使得它在运行时安全—防止XSM修改
*/
可选链接操作符是否修复它:previous?.length
?虽然previous?.length
抱怨“类型“never”上不存在属性“length”,但不确定它为什么在一种情况下抱怨,而在另一种情况下不抱怨。与previous!相同!。长度
如何声明值
在您的情况下,usePrevious
的返回类型不总是未定义吗?可选的链接操作符是否修复了它:previous?.length
?虽然previous?.length
抱怨“类型“never”上不存在属性“length”,但不确定它为什么在一种情况下抱怨,而在另一种情况下不抱怨。与previous!相同!。长度
如何声明值
呢?在您的情况下,useproval
的返回类型不总是未定义吗?谢谢,这很有效。我刚刚意识到我应该在所有地方使用像这样的泛型,谢谢,这很有效。我刚刚意识到我应该在所有地方使用这样的泛型