可能是通过使用包装器,而不是重载.包装器中的操作取决于您希望代码的类型安全程度.
您只需假设数据将以您期望的方式呈现,在这种情况下,您只需要一个包装器,但出错的机会很多:
// Lots of opportunities for error here
import { getMetadata as realGetMetadata } from "wherever";
// ...
export function getMetadata<T>(key: string): T {
return realGetMetadata(key) as T;
}
(I've left off the 100 parameter there and below because I don't know what it's for, but it's largely tangential to the discussion.)
但同样,这并不是非常安全的类型,您只是在断言您拥有正确的值.理想情况下,在开发和试运行阶段达到least岁时,您希望证明断言是正确的,如果不正确则会引发错误.
import { getMetadata as realGetMetadata } from "wherever";
// ...
export function getMetadataString(key: string) {
const value = realGetMetadata(key);
if (typeof value !== "string") {
throw new ValidationError(/*...*/);
}
return value;
}
export function getMetadataNumber(key: string) {
const value = realGetMetadata(key);
if (typeof value !== "number") {
throw new ValidationError(/*...*/);
}
return value;
}
// ...
您最终得到了一系列函数(特别是在有许多不同的对象格式需要验证的情况下),但是您正在确保类型安全.
为了避免有太多的函数,您可以让验证器函数与键一起传递,但除非您有某种方式聚合它们的方法,否则如果您需要验证对象或元组 struct ,您最终得到的函数(加上基本调用)也是一样多.
为了解决这个问题,您可以使用旨在以类型安全的方式验证或解析数据的库.其中一个这样的库是zod
,但虽然我将以它为例,但它并不是城里唯一的游戏,如果你愿意,你甚至可以自己玩.一百零二
下面是一个zod
个例子:
import { z } from "zod";
import { getMetadata as realGetMetadata } from "wherever";
// ...
export function getMetadata<
SchemaType extends z.ZodTypeAny,
ResultType extends ReturnType<SchemaType["parse"]>
>(key: string, schema: SchemaType): ResultType {
const rawValue = realGetMetadata(key);
const value = schema.parse(rawValue);
return value;
}
然后,例如:
// To get a string:
const str = getMetadata("foo", z.string());
// To get a number:
const num = getMetadata("foo", z.number());
// To get an object with `name` and `age` properties:
const num = getMetadata("foo", z.object({
name: z.string(),
age: z.number(),
}));
// ...
正如您从上面的代码中看到的,zod
个对象有一个parse
函数,其返回类型与您所描述的类型匹配.因此,在上面的代码中,返回类型是string
,然后是number
,然后是{name: string; age: number; }
.这种方法的一个优点是,执行元数据检索的代码定义了它期望看到的内容.(可以像上面那样内联,也可以通过创建和重用架构对象来实现.)
If你想避免验证的运行时成本,你could在生产环境中绕过它(基于环境的分支,只需用类型断言将rawValue
分配给value
).在某些情况下,这可能是合适的,尽管这取决于您使用的库(如果有的话)和您使用的功能.例如,大多数(我假设)将超越简单的"它是字符串吗?或者是一个数字?"and offer"至少有N个字符长吗?或者是在X和Y之间?"你可能也想在生产中使用它.