打字稿。为啥功能接口中描述的“返回值”类型没有严格执行?

Posted

技术标签:

【中文标题】打字稿。为啥功能接口中描述的“返回值”类型没有严格执行?【英文标题】:Typescript. Why described "return value's" type in functional interface is being not strict implemented?打字稿。为什么功能接口中描述的“返回值”类型没有严格执行? 【发布时间】:2019-10-21 11:38:39 【问题描述】:

我试图在一个地方描述具有特定部分类型返回值的功能接口。

我的界面IStore 只包含一个属性test。如果我将我的接口设置为某个函数foo,它还返回一个带有另一个属性的哈希图,打字稿会告诉“一切正常”。但是我需要得到 ts 错误,而来自foo 的返回值与Partial<IStore> 不严格匹配。在foo没有明确指示返回值

interface IStore test: string;
type IFunction<S> = (store: S) => Partial<S>;

// no ts errors. WHY?
// that's NO OK for me.
const foo1: IFunction<IStore> = () => (
  test: '',
  test2: '' // why no errors in this row?
);

// ts error,
// it is working, but not my target case
const foo2: IFunction<IStore> = (): IStore => (
  test: '',
  test2: '' // error here
);


// Meanwhile...
// no ts error
// that's OK
const foo3: IFunction<IStore> = () => (
  test: ''
);

// and...
// ts error: Type ' test2: string; ' has no properties
// in common with type 'Partial<IStore>'
// that's OK
const foo4: IFunction<IStore> = () => (
  test2: ''
);

如果没有... (): IStore =&gt; ...,如何在“case 1”(foo1) 中从“case 2”(foo2) 得到错误?

【问题讨论】:

这是 TypeScript 中的 known issue。函数表达式返回时不会发生过多的属性检查,尽管人们期望它会发生。 TypeScript 没有直接的方法来指定 exact types,这正是您想要的。有一些方法可以获得类似的行为,但它们可能需要您使用像 const foo = asIFunctionIstore(...) 这样的辅助函数,而不是您想要的 const foo: IFunction&lt;IStore&gt; = ...。不确定您是否会对这样的解决方案感兴趣 【参考方案1】:

Typescript 有时会应用严格的属性检查,有时则不会。应用冒号时,它始终应用严格的属性检查(函数参数除外)。当不应用冒号时,它比较结构以查看是否与别名的结构匹配,如果为 true,则类型兼容,这是结构类型的核心。此冒号检查适用于范围内最近的冒号。

IStore 或 Partial 当冒号应用于 ReturnType 时只能有 test: string 或 ;但绝不是多余的属性。 即

const foo2 = (): Partial<IStore> => (); // is allowed but...
const foo2 = (): Partial<IStore> => (notALlowed: true); // not allowed

当不应用冒号时,它会在关闭多余属性的情况下进行结构类型检查,这是函数的类型别名的情况。

type IFunction<S> = (store: S) => Partial<S>;


const foo1: IFunction<IStore> = () => (
  test: '',
  test2: '' // why no errors in this row?
);

现在可能会有一些混乱,因为两个 sn-ps 都实现了一个冒号,但区别在于冒号的位置,在函数的情况下,左边的冒号只会对函数参数应用严格的属性检查,但是绝不是 ReturnType。

【讨论】:

以上是关于打字稿。为啥功能接口中描述的“返回值”类型没有严格执行?的主要内容,如果未能解决你的问题,请参考以下文章

为啥打字稿在实现抽象函数时忽略严格的空检查?

为啥打字稿将联合中的属性标记为不存在?

使用 eslint 从 graphql 解析器返回啥严格的打字稿类型?

打字稿:在没有实际扩展/扩大的情况下捕获/推断类型的约束

为啥打字稿抱怨对象必须是扩展类型中的对象

打字稿重载箭头功能不起作用