Typescript 为什么偏袒<;(param1:ParamType,…)=>;返回类型>;表现得像其他人吗?

Typescript 为什么偏袒<;(param1:ParamType,…)=>;返回类型>;表现得像其他人吗?,typescript,type-level-computation,Typescript,Type Level Computation,这段代码为什么要编译 const fn: Partial<(a: string) => number> = "LOL DIS IS A STRING"; // any non-null value // Though this won't compile under strict null checks: const fn: Partial<(a: string) => number> = null; const fn: Partial<(a: str

这段代码为什么要编译

const fn: Partial<(a: string) => number> = "LOL DIS IS A STRING"; // any non-null value

// Though this won't compile under strict null checks:
const fn: Partial<(a: string) => number> = null;
const fn: Partial<(a: string) => number> = undefined;
常量fn:Partial number>=“LOL DIS是一个字符串”//任何非空值
//虽然在严格的空检查下无法编译:
常数fn:部分数>=null;
常数fn:部分数>=未定义;


当使用方法应用于类型时,会出现此问题。

简短回答:
部分数>
计算为
{}
,空对象类型,类似于
未知
,不包括
未定义

详细回答:

  • Partial
    定义为
    {[K in keyof T]?:T[K]}
    。它迭代
    T
    的属性,并使每个属性都是可选的。但是,在这种情况下,
    keyof((a:string)=>number)
    never
    ;它没有属性。(好的,函数类型确实有来自
    函数
    接口的属性,例如
    绑定
    调用
    长度
    ,等等,还有来自
    对象
    接口的属性,例如
    到字符串
    ,等等。但是这些属性通常不适用于迭代,因此它们是因此
    Partialnumber>
    返回一个没有属性的对象类型:空类型
    {}

  • 空类型
    {}
    的行为几乎与此类似。这是因为TypeScript中的对象类型是“打开的”,您可以向类型添加属性,而不会使其不兼容。因此

    interface Foo {a: string}
    interface Bar extends Foo {b: string}
    
    Bar
    类型(
    {a:string,b:string}
    )的值也可分配给
    Foo
    类型(
    {a:string}
    )。如果您从逻辑上得出结论,那么任何对象类型都可以分配给空对象类型
    {}
    。此外,如果对象类型的属性是兼容的,则将诸如
    string
    number
    之类的基本类型视为可分配给对象类型。由于
    string
    number
    类型确实具有属性(如
    length
    toFixed
    等),因此它们也可分配给空对象类型。只有
    null
    undefined
    在尝试从它们读取属性时实际抛出运行时错误,因此这两个值不被视为可分配给
    {}


如果您想执行递归映射类型,那么应该确定在命中函数类型属性时希望看到的结果,然后使用。显然,要做的事情就是保持方法函数类型不变(尽管方法的存在可能是可选的?不确定)

那看起来像

type DeepPartial2<T> = T extends Function ? T : {
  [K in keyof T]?: DeepPartial2<T[K]>
}

interface Foo {
  name: string,
  age: number,
  yell(): void,
  friend: Foo
}

type DPFoo = DeepPartial2<Foo>;
/*
type DPFoo = {
    name?: string | undefined;
    age?: number | undefined;
    yell?: (() => void) | undefined;
    friend?: DPFoo | undefined;
}
*/
类型DeepPartial2=T扩展函数?T:{
[K in keyof T]?:深度部分2
}
接口Foo{
名称:string,
年龄:数字,,
空,
朋友:福
}
类型DPFoo=DeepPartial2;
/*
类型DPFoo={
名称?:字符串|未定义;
年龄?:数字|未定义;
yell?:(()=>void)|未定义;
朋友?:DPFoo |未定义;
}
*/
好吧,希望这会有帮助;祝你好运


简短回答:
部分数字>
计算为
{}
,空对象类型,类似于
未知
,排除了
未定义

详细回答:

  • Partial
    定义为
    {[K in keyof T]?:T[K]}
    。它迭代
    T
    的属性,并使每个属性都是可选的。但是,在这种情况下,
    keyof((a:string)=>number)
    never
    ;它没有属性。(好的,函数类型确实有来自
    函数
    接口的属性,例如
    绑定
    调用
    长度
    ,等等,还有来自
    对象
    接口的属性,例如
    到字符串
    ,等等。但是这些属性通常不适用于迭代,因此它们是因此
    Partialnumber>
    返回一个没有属性的对象类型:空类型
    {}

  • 空类型
    {}
    的行为几乎与此类似。这是因为TypeScript中的对象类型是“打开的”,您可以向类型添加属性,而不会使其不兼容。因此

    interface Foo {a: string}
    interface Bar extends Foo {b: string}
    
    Bar
    类型(
    {a:string,b:string}
    )的值也可分配给
    Foo
    类型(
    {a:string}
    )。如果您从逻辑上得出结论,那么任何对象类型都可以分配给空对象类型
    {}
    。此外,如果对象类型的属性是兼容的,则将诸如
    string
    number
    之类的基本类型视为可分配给对象类型。由于
    string
    number
    类型确实具有属性(如
    length
    toFixed
    等),因此它们也可分配给空对象类型。只有
    null
    undefined
    在尝试从它们读取属性时实际抛出运行时错误,因此这两个值不被视为可分配给
    {}


如果您想执行递归映射类型,那么应该确定在命中函数类型属性时希望看到的结果,然后使用。显然,要做的事情就是保持方法函数类型不变(尽管方法的存在可能是可选的?不确定)

那看起来像

type DeepPartial2<T> = T extends Function ? T : {
  [K in keyof T]?: DeepPartial2<T[K]>
}

interface Foo {
  name: string,
  age: number,
  yell(): void,
  friend: Foo
}

type DPFoo = DeepPartial2<Foo>;
/*
type DPFoo = {
    name?: string | undefined;
    age?: number | undefined;
    yell?: (() => void) | undefined;
    friend?: DPFoo | undefined;
}
*/
类型DeepPartial2=T扩展函数?T:{
[K in keyof T]?:深度部分2
}
接口Foo{
名称:string,
年龄:数字,,
空,
朋友:福
}
类型DPFoo=DeepPartial2;
/*
类型DPFoo={
名称?:字符串|未定义;
年龄?:数字|未定义;
yell?:(()=>void)|未定义;
朋友?:DPFoo |未定义;
}
*/
好吧,希望这会有帮助;祝你好运