Bri*_*ian 10 typescript reactjs react-hooks
在我的 React 应用程序中,我使用非空断言 (!) 来告诉 TS 来自useContext钩子的值不为空。它运行良好,似乎是非空断言的教科书用例,但根据推荐的 eslint 规则,非空断言是一个警告。
作为 TypeScript 的新手,我想确保在处理这些情况时不会错过通用模式或最佳实践方法。或者也许有不同的方式来键入user下面示例中的对象。
// context.ts
interface State {
user: User | null; // User type is defined elsewhere, has 'id' and 'email'
}
const state: State = {
user: null,
};
Run Code Online (Sandbox Code Playgroud)
state.user。// App.tsx
return state.user ? <Dashboard /> : <Login />;
Run Code Online (Sandbox Code Playgroud)
state.user,但我仍然看到以下错误。// Dashboard.tsx
const { state } = React.useContext(context);
const name = state.user.firstName; // Object is possibly 'null'.
const { id, email } = state.user; // Property 'id/email' does not exist on type 'User | null'.
Run Code Online (Sandbox Code Playgroud)
state = { user: null }因此 null 必须可分配给该User类型。预期可能的答案不能解决我关于最佳实践/模式的问题:
我知道如何禁用@typescript-eslint/no-non-null-assertion规则,这不是我正在寻找的解决方案。
我知道如果我在第一个示例中使用可选链接,则可以避免错误和非空断言警告,如下所示:const name = state.user?.firstName;但这并不能回答我的问题。在这种情况下,我实际上更喜欢非空断言,因为会更明确。
谢谢!
有几个选项供您选择:
明确检查user不是,null如果是则抛出
定义一个“已登录”状态接口并编写一个钩子,在检查user未登录后返回该状态接口null
定义一个“已登录”状态接口并编写一个类型断言函数Dashboard,然后在或钩子中使用它
它们之间的共同主题不仅仅是断言 that userisn't null,而是在运行时证明它,以便主动且清晰地捕获使用statewith的编程错误null,而不是看似随机的“Can't use X of null”错误。
由于用户只有Dashboard在登录后才能看到该组件,而当他们登录时,上下文user成员将不会是null,因此您可以显式检查:
const { state } = React.useContext(context);
const { user } = state;
if (!user) {
throw new Error(`ERROR: User reached Dashboard with null 'user' in context`);
}
// ...code uses `user`...
Run Code Online (Sandbox Code Playgroud)
这样,TypeScript 就知道组件代码的其余部分user不是null,并且如果编程错误导致尝试使用Dashboardwhen useris ,您会得到一个明显的错误null。
或者,您可以定义LoggedInState:
interface LoggedInState {
user: User;
}
Run Code Online (Sandbox Code Playgroud)
并编写一个可重用的钩子:
function useLoggedInContext(context: ContextType): LoggedInState {
const { state } = React.useContext(context);
if (!state.user) {
throw new Error(`ERROR: User reached logged-in-only component with null 'user' in context`);
}
return state as LoggedInState;
}
Run Code Online (Sandbox Code Playgroud)
它仍然有一个类型断言,但在一个可重用的位置,上面的运行时代码证明它是一个正确的断言。
然后在Dashboard(和其他地方):
const { state } = useLoggedIncontext(context);
// ...
Run Code Online (Sandbox Code Playgroud)
您可以将其包装在类型断言函数中:
function assertIsLoggedInState(state: State): asserts state is LoggedInState {
if (!state.user) {
throw new AssertionError(`'state' has a null 'user' member, expected a logged-in state`);
}
}
Run Code Online (Sandbox Code Playgroud)
然后直接在以下位置使用它Dashboard:
const { state } = React.useContext(context);
assertIsLoggedInState(state);
// ...code can use `state.user`, which TypeScript now knows can't be `null`
Run Code Online (Sandbox Code Playgroud)
或者在该钩子中使用它useLoggedInContext:
function useLoggedInContext(context: ContextType): LoggedInState {
const { state } = React.useContext(context);
assertIsLoggedInState(state);
return state; // TypeScript knows this is a LoggedInState
}
Run Code Online (Sandbox Code Playgroud)
作为对第一个的一个小调整:如果您不需要state其他任何内容,您可以合并前两个语句:
const { state: { user } } = React.useContext(context);
// ...
Run Code Online (Sandbox Code Playgroud)
那只宣示user,不宣示state。如果您还有其他state需要的东西,可以在之后添加user。
| 归档时间: |
|
| 查看次数: |
4182 次 |
| 最近记录: |