代码之家  ›  专栏  ›  技术社区  ›  SystematicFrank

从模板中排除属性

  •  1
  • SystematicFrank  · 技术社区  · 6 年前

    我有这段代码,可以从接口中排除属性

    type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
    
    interface MyType {
      id: string
      timeout: number
      delta: number
    }
    
    let value: Omit<MyType, 'id'> = {
      timeout: 10,
      delta: 5,
    }
    

    可以,但我不能从泛型类型中排除该属性,如:

    function foo<T>(x: T) {
      let value: Omit<T, 'id'> = {
        timeout: 10,
        delta: 5,
      }
    }
    foo<MyType>({ timeout: 10, delta: 5 })
    

    现在我收到错误信息 Type '"id"' does not satisfy the constraint 'keyof T' 我做错什么了?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Titian Cernicova-Dragomir    6 年前

    这是因为编译器不能仅基于函数声明检查if type T 实际拥有财产 id . 我们可以添加一个约束来告诉编译器将传入的内容将具有 身份证件 属性:

    function foo<T extends { id: string }>(x: Omit<T, 'id'>) {
        let value: Omit<T, 'id'> = x;
    }
    foo<MyType>({ timeout: 10, delta: 5 })
    

    你会注意到我没有初始化 value 函数中的变量具有对象文本,这是因为如果不知道完整类型,则无法创建对象文本。我们所知道的 T型 那是has和 身份证件 财产,我们对其他财产一无所知 T型 有,他们有什么类型,如果他们需要。

    如果您真的需要在函数中初始化泛型类型的变量,那么( 不安全的 )方法是使用类型断言:

    function foo<T extends MyType>(x: Omit<T, 'id'>) {
        let value = {
            timeout: 10,
            delta: 5,
        } as unknown as Omit<T, 'id'> // replace unknown with any for ts before 3.0
    }