【问题标题】:Expect a 'Type' from third party library functions期望来自第三方库函数的“类型”
【发布时间】:2016-12-03 07:41:37
【问题描述】:

我对 TypeScript 很陌生。我有一个场景,我想为一个变量分配一个类型,该变量的值是从第三方库的函数返回的,并且它有自己的类型定义。

例如:

import {omit} from 'lodash'

interface ITest {
  a: String;
}

const foo: Object = {
  a: "dfdf",
  b: "sdfsdf",
}

const expected: ITest = omit(foo, 'b')

这显示了这个错误

[ts] 类型“{}”不可分配给类型“ITest”。

类型“{}”中缺少属性“a”。

是我做错了还是不可能?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    发生这种情况是因为omit 对其返回类型的约束很少,并且默认返回{}。如果您想深入了解,请查看the definitions for omit

    interface LoDashStatic {
        omit<TResult extends {}, T extends {}>(
            object: T,
            ...predicate: (StringRepresentable|StringRepresentable[])[]
        ): TResult;
    }
    

    这表示 omit 有两个通用参数(TResultT,它们都至少是 {})。它还具有一个必需参数(object)和 0 个或多个 predicates(字符串,或多或少)。泛型参数 T 是其输入的类型,TResult 是函数的整体返回类型。

    当你不指定泛型参数时,TypeScript 会推断它们。但是,这些参数彼此无关,或者其他很多,因此很难准确地做到这一点。它可以推断T:它是给定参数的类型。不过对于TResult,它什么都没有。如果您调用该函数并立即使用该值,则在某些情况下足以推断出该函数应返回什么(所以TResult 是什么),但在您的情况下它不是,因此推断为{}.

    一旦您在代码中实际调用了 omit,然后尝试将 {} 分配给 ITest,这绝对不安全 - 可能会得到一个空对象没有a 属性,这是不正确的。

    你有两个选择来解决这个问题:

    • 使用类型断言:const expected = &lt;ITest&gt; omit(foo, 'b')

      在这里你告诉编译器你确定这是一个ITest。它允许这样做(并给expected 一个ITest 类型),只要它是可能你是正确的 - 你不必绝对正确,就像您对普通作业所做的那样。

    • 通过提供omit 明确使用的泛型参数来指定函数的返回类型:const expected = omit&lt;ITest, {}&gt;(foo, 'b')

      目前这些参数是自动推断的,但是这些类型定义没有任何方法可以派生出“正确”类型(“foo 的类型,但没有 'a'”),所以你最终得到了最可能的一般返回类型:{}。如果您明确设置这些泛型,您可以更紧密地控制它。您实际上只想在此处指定一个通用参数(返回类型),但遗憾的是您不能这样做:您必须同时指定两者,或者都不指定。

    我个人会使用类型断言,但我认为从这一点来看,这归结为个人品味问题。

    【讨论】:

    • 说得好。 omit&lt;ITest, {}&gt;(foo, 'b') 中的 {} 是什么意思?
    • 我已经添加了关于类型定义本身的更多细节。有两个通用参数 - TResult 和 T - 并且omit&lt;ITest, {}&gt;(foo, 'b') 将 TResult 设置为 ITest 并将 T 设置为 {}。 TResult 是返回类型(这是您要更改的),T 是参数(foo)的类型,您可能并不关心,但如果您想指定一个,则必须同时指定两者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多