可以根据类型参数覆盖的打字稿类型
Typescript types that can be overwritten based on type arguments
我正在尝试找出最好的方法来告诉打字稿编译器 returns T | null
的函数在某些情况下肯定会是 T
。
也许我在考虑这个错误,在这种情况下我也乐于接受新想法,这里是片段:
type ValueOrNull<T, N> = N extends false ? T | null : T;
export function getCookie<T = any, N = false>(name: string): ValueOrNull<T, N> {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
const [, , value] = match;
return parseCookieValue(value) as T;
}
return null;
}
我的想法是,如果我可以按如下方式调用函数:getCookie<TMyCookie, true>("my_cookie")
typescript 会知道我确定 cookie 会在那里,并且函数不会 return null。例如登录成功后。
N extends false ?
感觉不对但是N === false
不行。
编译器错误是Type 'null' is not assignable to type 'ValueOrNull<T, N>'.ts(2322)
非常感谢
您可以使用函数重载和第二个参数很容易地做到这一点;当程序员(不可避免地)“知道”cookie 存在但它不存在时,这还可以让您建立一个有用的解释性错误:
export function getCookie<T>(name: string, required: true): T;
export function getCookie<T>(name: string, required?: false): T | null;
export function getCookie<T>(name: string, required?: boolean): T | null {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
const [, , value] = match;
// You'll want to put your `parseCookingvalue` back here,
// the `as any as T` is just because we don't have that
// function available to use in the question.
return /*parseCookieValue(value)*/ value as any as T;
} else if (required) {
throw new Error(`Required cookie "${name}" was not found`);
}
return null;
}
const a = getCookie<string>("a", true);
// ^? −−−− type is string
const b = getCookie<string>("b", false);
// ^? −−−− type is string | null
不过,这里有一个替代方案:您可以让 getCookie
相当简单,并拥有一个 general-use type assertion function,您可以在任何地方使用它来取回可能 null
或 undefined
而你“知道”它不是 null
或 undefined
:
export function getCookie<T>(name: string): T | null {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
const [, , value] = match;
// You'll want to put your `parseCookingvalue` back here,
// the `as any as T` is just because we don't have that
// function available to use in the question.
return /*parseCookieValue(value)*/ value as any as T;
}
return null;
}
export function assertIsNotNullish<T>(value: T | null | undefined): asserts value is T {
if (value == null) {
throw new Error(`Expected non-nullish value, got ${value}`);
}
}
const a = getCookie<string>("a");
assertIsNotNullish(a);
console.log(a);
// ^? −−−− type is string
const b = getCookie<string>("b");
console.log(b);
// ^? −−−− type is string | null
我正在尝试找出最好的方法来告诉打字稿编译器 returns T | null
的函数在某些情况下肯定会是 T
。
也许我在考虑这个错误,在这种情况下我也乐于接受新想法,这里是片段:
type ValueOrNull<T, N> = N extends false ? T | null : T;
export function getCookie<T = any, N = false>(name: string): ValueOrNull<T, N> {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
const [, , value] = match;
return parseCookieValue(value) as T;
}
return null;
}
我的想法是,如果我可以按如下方式调用函数:getCookie<TMyCookie, true>("my_cookie")
typescript 会知道我确定 cookie 会在那里,并且函数不会 return null。例如登录成功后。
N extends false ?
感觉不对但是N === false
不行。
编译器错误是Type 'null' is not assignable to type 'ValueOrNull<T, N>'.ts(2322)
非常感谢
您可以使用函数重载和第二个参数很容易地做到这一点;当程序员(不可避免地)“知道”cookie 存在但它不存在时,这还可以让您建立一个有用的解释性错误:
export function getCookie<T>(name: string, required: true): T;
export function getCookie<T>(name: string, required?: false): T | null;
export function getCookie<T>(name: string, required?: boolean): T | null {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
const [, , value] = match;
// You'll want to put your `parseCookingvalue` back here,
// the `as any as T` is just because we don't have that
// function available to use in the question.
return /*parseCookieValue(value)*/ value as any as T;
} else if (required) {
throw new Error(`Required cookie "${name}" was not found`);
}
return null;
}
const a = getCookie<string>("a", true);
// ^? −−−− type is string
const b = getCookie<string>("b", false);
// ^? −−−− type is string | null
不过,这里有一个替代方案:您可以让 getCookie
相当简单,并拥有一个 general-use type assertion function,您可以在任何地方使用它来取回可能 null
或 undefined
而你“知道”它不是 null
或 undefined
:
export function getCookie<T>(name: string): T | null {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
const [, , value] = match;
// You'll want to put your `parseCookingvalue` back here,
// the `as any as T` is just because we don't have that
// function available to use in the question.
return /*parseCookieValue(value)*/ value as any as T;
}
return null;
}
export function assertIsNotNullish<T>(value: T | null | undefined): asserts value is T {
if (value == null) {
throw new Error(`Expected non-nullish value, got ${value}`);
}
}
const a = getCookie<string>("a");
assertIsNotNullish(a);
console.log(a);
// ^? −−−− type is string
const b = getCookie<string>("b");
console.log(b);
// ^? −−−− type is string | null