我正在做一个文件共享服务。
我有一个名为ValidatedPath
的类型,它表示通过validate()函数处理的字符串,该函数检查字符串是否是有效路径。
export type ValidatedPath = string & { __type: "ValidatedPath" };
function validate(path: string): ValidatedPath | null {
// Severely shortened for clarity
if(false === regex.test(path)) return null;
return path as ValidatedPath;
}
问题是,ValidatedPath实际上并不表示文件系统中的实际路径,而只是相对于某个目录的有效路径。
例如:folder/folder2/file
是一个ValidatedPath,但真实的的路径应该是/Users/hello/folder/folder2/file
,我将在通过path.join(baseDirectory, validatedPath)
调用后获得它
但是,因为ValidatedPath是string的子类型,所以我可以将其传递到文件系统函数中,这将导致错误,因为这不是正确的行为。
例如:
async function rename(original: ValidatedPath, destination: ValidatedPath) {
await fs.rename(original, destination); // This is allowed, but it's wrong!
const realOriginal: string = path.join(baseDirectory, original);
const realDestination: string = path.join(baseDirectory, destination);
await fs.rename(realOriginal, realDestination); // This is correct!
}
解决方案:
我有一些解决方案,我目前不知道如何实施,如果他们甚至可能。
方案一:
文件系统函数接受一个名为PathLike
的类型作为参数,该类型在某个node_modules文件中定义。我能以某种方式重写或修改这个外部定义的类型PathLike
吗?
// Externally defined
type PathLike = string | Buffer | URL;
function rename(oldPath: PathLike, newPath: PathLike): Promise<void>;
方案二:
我可以让ValidatedPath
不是string的子集:
export type ValidatedPath = Omit<string, "toLocaleString">;
这将使它不再有效地将ValidatedPath传递到文件系统函数。但是,这将使它不能与path.join()
一起工作,因为它只接受字符串。总是写很烦人,
const realPath = path.join(baseDirectory, validatedPath as string);
但如果我可以修改单个函数路径,它会少得多。join采用string或ValidatedPath,这样就不再需要类型Assert。我能以某种方式覆盖或修改这个外部定义的函数定义path.join
吗?
如果以上都不可能,可能只是我被迫使用解决方案2,而不重写path.join
,每次我想使用一个接受字符串的函数时,类型AssertValidatedPaths作为字符串。这很烦人,但我可以忍受。我只是觉得一定有更好的解决办法。
先谢谢你了。
1条答案
按热度按时间rqqzpn5f1#
如果使用多次强制转换让您感到困扰,那么 Package 器函数将是一个解决方案。您可以创建自己的
pathJoin
函数,该函数接受您的ValidatedPath
类型并将其转换为字符串类型,或者使用String
函数将其转换为字符串并返回路径的调用。public void run().