英文:
Leave as default type on generic type parameter
问题
const data: Foo<number, string, number> = {
ID: 1,
Name: "apache",
IsActive: 1,
}
英文:
I am trying to bypass some optional generic type parameter and leave it as a default that has been defined.
This is an example script:
interface Foo<T, T1 = string, T2 = boolean> {
ID: T
Name: T1
IsActive: T2
}
There is 3 type parameters are following:
T
-- it's requiredT1
-- optional, default isstring
T2
-- optional, default isboolean
I want to create data
with specification below:
T
--number
T1
-- <DEFAULT which isstring
>T2
--number
const data:Foo<number, ..., number> = {
ID: 1,
Name: "apache", // the name type should be a string
IsActive: 1,
}
答案1
得分: 2
目前还没有这样的语法来“跳过”一个通用类型参数,无论是为了使用默认值还是为了让编译器推断类型参数。这方面有一个长期存在的开放功能请求,可以在microsoft/TypeScript#26242中找到;如果这个功能被实现,那么也许你就能够编写类似于Foo<number, , number>
、Foo<number, *, number>
或Foo<number, infer, number>
之类的代码。
在那之前,你只能自己写类型,比如Foo<number, string, number>
,或者以某种方式绕过它。
一个可能的解决方法,如果“跳过”的目的是为了获取默认值,是创建一个自定义类型来表示“跳过”,然后重新编写你的类型以识别它。例如:
interface $ { ___SIGIL___: true; } // $ 表示“跳过”
type Default<T, U> = [T] extends [$] ? U : T;
现在,不再使用type F<T = X, U = Y, V = Z>
,而是写成type MyF<T = $, U = $, V = $> = F<Default<T, X>, Default<U, Y>, Default<V, Z>>
。对于你的Foo
类型,看起来是这样的:
type FooT1Default = Foo<any> extends Foo<any, infer T1, any> ? T1 : never;
// type FooT1Default = string
type FooT2Default = Foo<any> extends Foo<any, any, infer T2> ? T2 : never;
// type FooT2Default = boolean
type MyFoo<T, T1 = $, T2 = $> =
Foo<T, Default<T1, FooT1Default>, Default<T2, FooT2Default>>;
我们可以进行测试:
type Example = MyFoo<number, $, number>;
// type Example = Foo<number, string, number>
const data: MyFoo<number, $, number> = {
ID: 1,
Name: "apache", // okay
IsActive: 1,
}
英文:
There is currently no such syntax to "skip" a generic type argument, either for the purposes of using a default or for having the compiler infer the type argument. There is a longstanding open feature request for this at microsoft/TypeScript#26242; if that is ever implemented, then maybe you'll be able to write Foo<number, , number>
or Foo<number, *, number>
, or Foo<number, infer, number>
or something.
Until then, you'll just have to write the type in yourself as Foo<number, string, number>
, or work around it somehow.
One possible workaround, if the purpose of "skipping" is to get the default, is to make a custom type to mean "skip" and rewrite your type to recognize that. For example:
interface $ { ___SIGIL___: true; } // $ means "skip"
type Default<T, U> = [T] extends [$] ? U : T;
And now instead of type F<T = X, U = Y, V = Z>
you'd write type MyF<T = $, U = $, V = $> = F<Default<T, X>, Default<U, Y>, Default<V, Z>>
. For your Foo
it look s like:
type FooT1Default = Foo<any> extends Foo<any, infer T1, any> ? T1 : never;
// type FooT1Default = string
type FooT2Default = Foo<any> extends Foo<any, any, infer T2> ? T2 : never;
// type FooT2Default = boolan
type MyFoo<T, T1=$, T2=$> =
Foo<T, Default<T1, FooT1Default>, Default<T2, FooT2Default>>;
And we can test it:
type Example = MyFoo<number, $, number>
// type Example = Foo<number, string, number>
const data: MyFoo<number, $, number> = {
ID: 1,
Name: "apache", // okay
IsActive: 1,
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论