带有打字稿的 React 路由器 v5 上所需的 url 参数,可以未定义

Or *_*har 41 types typescript react-router

我正在使用带有 TypeScript 的 react-router v5.1 并具有以下路由配置:

<Router basename="/" hashType="slash">
    <Switch>
        <Route path="/token/:tokenName">
            <TokenPage />
        </Route>
    </Switch>
</Router>

Run Code Online (Sandbox Code Playgroud)

我尝试访问组件中的 url 参数(tokenName),使用 useParams 钩子,如下所示:

const TokenPage: FC<TokenPageProps> = props => {
    const { tokenName } = useParams()
    ...
}

Run Code Online (Sandbox Code Playgroud)

但是,打字稿认为tokenNameparam 可以是未定义的:

错误的 tokenName 输入

这是没有意义的,因为如果 URL 中缺少参数,则反应路由器将不匹配此路由。

在这种情况下,我该如何解决打字问题?

KOT*_*TIX 105

在这种情况下,您的TokenPage代码不知道它被Route. 如果 URL 不包含正确的参数,您的组件将不会被呈现,这是正确的。但是 Typescript 并不知道这一点。

您在那里获得的默认类型是正确的,您应该在使用它之前检查该值。

如果您想覆盖类型,useParams则为泛型并接受指定返回值类型的类型。

interface ParamTypes {
  tokenName: string
}
const { tokenName } = useParams<ParamTypes>()
Run Code Online (Sandbox Code Playgroud)

编辑 09/29/20

最新的打字useParams改变。

export function useParams<Params extends { [K in keyof Params]?: string } = {}>(): Params;
Run Code Online (Sandbox Code Playgroud)

如您所见,新的默认值{}不会暗示包含的任何键,但通用约束确实假定值的类型为string

所以下面这行现在会产生一个Property 'tokenName' does not exist on type '{}'.TypeScript 错误。

const { tokenName } = useParams()
Run Code Online (Sandbox Code Playgroud)

要解决此问题,您可以useParams像第一个示例中那样输入具有已知参数的 ,或者像这样输入:

const { tokenName } = useParams<Record<string, string | undefined>>()
Run Code Online (Sandbox Code Playgroud)


Tim*_*Tim 12

使用原来的覆盖类型的思路,不需要新建命名接口,直接在类型参数中就可以完成:

const { tokenName } = useParams<{ tokenName: string }>();
Run Code Online (Sandbox Code Playgroud)

  • 这在 v6 中似乎不起作用,tokenName 仍然是字符串 | 不明确的。 (2认同)