输入类型定义时输出非未定义类型
Output non-undefined type when input type is defined
我刚刚写了这个函数:
const cloneUrl = <T extends (URL | undefined)>(url: T): T => url instanceof URL
? new URL(url.toString())
: undefined;
然而,这有错误(或者至少,错误非常接近于此):
'URL | undefined' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'URL | undefined'.
Type 'undefined' is not assignable to type 'T'. 'undefined' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'URL | undefined'.
显然我没有掌握 TypeScript 的一些基本知识...
我的目标是这样当 cloneUrl
被称为 URL 的类型调用时,return 类型是 URL,但是当cloneUrl
被调用的类型是 URL | undefined
,return 类型是 URL | undefined
.
示例:
class UrlWrapper {
private readonly _urlOne: URL
private readonly _urlTwo?: URL
constructor(urlOne: URL, urlTwo?: URL) {
this._urlOne = urlOne;
this._urlTwo = urlTwo;
}
get urlOne(): URL { return cloneUrl(this._urlOne); }
get urlTwo(): URL | undefined { return cloneUrl(this._urlTwo); }
}
看看 urlWrapper.urlOne
应该始终是一个不可定义的值,但 urlTwo
可以吗?
我尝试了不同类型的约束:
<T extends URL>
<T extends URL ? URL : undefined>
我试过不同的参数:
url?: T
url: T | undefined
我试过投射结果:
undefined as undefined
undefined as T | undefined
我试过将私有字段设为可选,或更改其类型。
我试过使用类型检查器函数:
const checkIsUrl = (url: unknown): url is URL => url instanceof URL;
...还有更多。
但是关于 TypeScript 如何思考类型,我没有正确的心智模型,所以我就是不明白。
我最近处理了这个问题,发现以下内容似乎可以使用带有 conditional return type 的泛型。 any
的使用很丑陋,但我不确定如何避免这种情况。这是巫术,我没有完全理解,但类型被推断为您所期望的。
export function cloneUrl<T extends URL | undefined>(value: T): T extends URL ? URL : undefined {
return value instanceof URL ? new URL(value.toString()) : (undefined as any);
}
let source: URL | undefined = new URL("test");
cloneUrl(source); // URL
source = undefined;
cloneUrl(source); // undefined
let optionalSource: URL | undefined;
cloneUrl(optionalSource); // URL or undefined
cloneUrl(new Date()); // Nope: Date isn't a URL
我刚刚写了这个函数:
const cloneUrl = <T extends (URL | undefined)>(url: T): T => url instanceof URL
? new URL(url.toString())
: undefined;
然而,这有错误(或者至少,错误非常接近于此):
'URL | undefined' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'URL | undefined'.
Type 'undefined' is not assignable to type 'T'. 'undefined' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'URL | undefined'.
显然我没有掌握 TypeScript 的一些基本知识...
我的目标是这样当 cloneUrl
被称为 URL 的类型调用时,return 类型是 URL,但是当cloneUrl
被调用的类型是 URL | undefined
,return 类型是 URL | undefined
.
示例:
class UrlWrapper {
private readonly _urlOne: URL
private readonly _urlTwo?: URL
constructor(urlOne: URL, urlTwo?: URL) {
this._urlOne = urlOne;
this._urlTwo = urlTwo;
}
get urlOne(): URL { return cloneUrl(this._urlOne); }
get urlTwo(): URL | undefined { return cloneUrl(this._urlTwo); }
}
看看 urlWrapper.urlOne
应该始终是一个不可定义的值,但 urlTwo
可以吗?
我尝试了不同类型的约束:
<T extends URL>
<T extends URL ? URL : undefined>
我试过不同的参数:
url?: T
url: T | undefined
我试过投射结果:
undefined as undefined
undefined as T | undefined
我试过将私有字段设为可选,或更改其类型。
我试过使用类型检查器函数:
const checkIsUrl = (url: unknown): url is URL => url instanceof URL;
...还有更多。
但是关于 TypeScript 如何思考类型,我没有正确的心智模型,所以我就是不明白。
我最近处理了这个问题,发现以下内容似乎可以使用带有 conditional return type 的泛型。 any
的使用很丑陋,但我不确定如何避免这种情况。这是巫术,我没有完全理解,但类型被推断为您所期望的。
export function cloneUrl<T extends URL | undefined>(value: T): T extends URL ? URL : undefined {
return value instanceof URL ? new URL(value.toString()) : (undefined as any);
}
let source: URL | undefined = new URL("test");
cloneUrl(source); // URL
source = undefined;
cloneUrl(source); // undefined
let optionalSource: URL | undefined;
cloneUrl(optionalSource); // URL or undefined
cloneUrl(new Date()); // Nope: Date isn't a URL