您可以使用类型构造函数和称为“幻象类型”(read a nice article about this here) 的东西来实现此目的,这是一种确保不能将类型直接分配给值的技术。
以下是使用这些技术的 StringOfLength<Min,Max> 类型示例:
type StringOfLength<Min, Max> = string & {
StringOfLength: unique symbol // this is the phantom type
};
// This is a type guard function which can be used to assert that a string
// is of type StringOfLength<Min,Max>
const isStringOfLength = <Min extends number, Max extends number>(
str: string,
min: Min,
max: Max
): str is StringOfLength<Min, Max> => str.length >= min && str.length <= max;
// type constructor function
export const stringOfLength = <Min extends number, Max extends number>(
input: unknown,
min: Min,
max: Max
): StringOfLength<Min, Max> => {
if (typeof input !== "string") {
throw new Error("invalid input");
}
if (!isStringOfLength(input, min, max)) {
throw new Error("input is not between specified min and max");
}
return input; // the type of input here is now StringOfLength<Min,Max>
};
// Now we can use our type constructor function
const myString = stringOfLength('hello', 1, 10) // myString has type StringOfLength<1,10>
// the type constructor fails if the input is invalid
stringOfLength('a', 5, 10) // Error: input is not between specified min and max
// The phantom type prevents us from assigning StringOfLength manually like this:
const a: StringOfLength<0, 10> = 'hello' // Type '"hello"' is not assignable to type { StringOfLength: unique symbol }
这里有一些限制 - 您不能阻止某人创建像 StringOfLength<-1, -300> 这样的无效类型,但您可以添加运行时检查,以检查 min 和 max 值传递给 stringOfLength 构造函数函数有效。