我有一个简单的react钩子,它返回一个函数.我希望此函数只接受传递到挂钩中的数组中的值.

钩子在这里:

type Options<P> = {
  pathname: string;
  rootPath: string;
  paths: P;
};

export const useLayoutPaths = <P extends string[]>(options: Options<P>) => {
  const { pathname, rootPath, paths } = options;

  if (paths.length === 0) {
    throw new Error("paths must be a non-empty array.");
  }

  const currentPath = pathname.substring(pathname.lastIndexOf("/") + 1);
  const value = paths.includes(currentPath) ? currentPath : paths[0];

  const getPath = (name: typeof paths[number]): string =>
    `${rootPath}/${String(name)}`;

  return { value, getPath };
};

我希望getPath函数只允许"paths"变量中存在的值.

以下是我目前的用法:

const { value, getPath } = useLayoutPaths({
  pathname,
  rootPath: `/department/${orgId}`,
  paths: ["trends", "comments"],
});

console.log(getPath("trends")) <-- Only allow "trends" or "comments"

推荐答案

您希望编译器跟踪作为paths属性传入的literal type个字符串.不幸的是,像P extends string[]这样的generic约束并没有发生这种情况.增加编译器将"foo"视为"foo"类型而不是string类型的可能性的一种方法是将泛型类型参数constrain设置为string.所以P extends string会更好.我们可以让Ppaths的元素类型,而不是paths本身,如下所示:

export const useLayoutPaths = <P extends string>(options: Options<P[]>) => {
   // impl
};

这将按需要工作,但编译器不喜欢让您在P的数组中查找string.更多信息请参见this question and answer.最简单的方法是在使用includes()之前将pathsP[]扩大到readonly string[]:

export const useLayoutPaths = <P extends string>(options: Options<P[]>) => {
  const { pathname, rootPath, paths } = options;

  if (paths.length === 0) {
    throw new Error("paths must be a non-empty array.");
  }

  const currentPath = pathname.substring(pathname.lastIndexOf("/") + 1);
  const value = (paths as readonly string[]).includes(currentPath) ? currentPath : paths[0];

  const getPath = (name: typeof paths[number]): string =>
    `${rootPath}/${String(name)}`;

  return { value, getPath };
};

现在一切按您的意愿进行:

console.log(getPath("trends")) // okay
getPath("oops"); // error!

Playground link to code

Typescript相关问答推荐

TypScript错误:类型{ children:ReactNode; }与动态React组件中的IntrinsicLedger类型没有共同的属性

脉轮ui打字脚本强制执行图标按钮的咏叹调标签-如何关闭

类型脚本接口索引签名

有没有一种方法可以在保持类型的可选状态的同时更改类型?

将props传递给子组件并有条件地呈现它''

Webpack说你可能需要在Reactjs项目中增加一个加载器''

如何使用类型谓词将类型限制为不可赋值的类型?

嵌套对象的类型

有没有可能产生输出T,它在视觉上省略了T中的一些键?

Vue3 Uncaught SyntaxError:每当我重新加载页面时,浏览器控制台中会出现无效或意外的令牌

TypeScrip泛型类未提供预期的类型错误

如何将父属性类型判断传播到子属性

vue-tsc失败,错误引用项目可能无法禁用vue项目上的emit

如何按属性或数字数组汇总对象数组

字符串文字联合的分布式条件类型

重写返回任何

Typescript泛型调用对象';s方法

TypeScript:如何使用泛型和子类型创建泛型默认函数?

Typescript:是否将联合类型传递给重载函数?

对象只能使用 Typescript 中另一个对象的键