ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Difference between extending and intersecting interfaces in TypeScript?

2022-05-27 17:34:48  阅读:192  来源: 互联网

标签:TypeScript sheet type interfaces share extending interface data se


Difference between extending and intersecting interfaces in TypeScript?

Ask Question Asked 3 years, 7 months ago Modified 10 months ago Viewed 18k times   88

Let's say the following type is defined:

interface Shape {
  color: string;
}

Now, consider the following ways to add additional properties to this type:

Extension

interface Square extends Shape {
  sideLength: number;
}

Intersection

type Square = Shape & {
  sideLength: number;
}

What is the difference between both approaches?

And, for sake of completeness and out of curiosity, are there other ways to yield comparable results?

Share Improve this question   edited Oct 6, 2018 at 17:01     asked Oct 6, 2018 at 16:56 user avatar Willem-Aart 1,87011 gold badge1717 silver badges2323 bronze badges Add a comment

1 Answer

98  

Yes there are differences which may or may not be relevant in your scenario.

Perhaps the most significant is the difference in how members with the same property key are handled when present in both types.

Consider:

interface NumberToStringConverter {
  convert: (value: number) => string;
}

interface BidirectionalStringNumberConverter extends NumberToStringConverter {
  convert: (value: string) => number;
}

The extends above results in an error because the derriving interface declares a property with the same key as one in the derived interface but with an incompatible signature.

error TS2430: Interface 'BidirectionalStringNumberConverter' incorrectly extends interface 'NumberToStringConverter'.

  Types of property 'convert' are incompatible.
      Type '(value: string) => number' is not assignable to type '(value: number) => string'.
          Types of parameters 'value' and 'value' are incompatible.
              Type 'number' is not assignable to type 'string'.

However, if we employ intersection types

type NumberToStringConverter = {
  convert: (value: number) => string;
}

type BidirectionalStringNumberConverter = NumberToStringConverter & {
  convert: (value: string) => number;
}

There is no error whatsoever and further given

// And this is a good thing indeed as a value conforming to the type is easily conceived
const converter: BidirectionalStringNumberConverter = {
    convert: (value: string | number) => {
        return (typeof value === 'string' ? Number(value) : String(value)) as string & number; // type assertion is an unfortunately necessary hack.
    }
}

const s: string = converter.convert(0); // `convert`'s call signature comes from `NumberToStringConverter`

const n: number = converter.convert('a'); // `convert`'s call signature comes from `BidirectionalStringNumberConverter`

Playground Link

This leads to another interesting difference, interface declarations are open ended. New members can be added anywhere because multiple interface declarations with same name in the same declaration space are merged.

Here is a common use for merging behavior

lib.d.ts

interface Array<T> {
  // map, filter, etc.
}

array-flat-map-polyfill.ts

interface Array<T> {
  flatMap<R>(f: (x: T) => R[]): R[];
}

if (typeof Array.prototype.flatMap !== 'function') {
  Array.prototype.flatMap = function (f) { 
    // Implementation simplified for exposition. 
    return this.map(f).reduce((xs, ys) => [...xs, ...ys], []);
  }
}

Notice how no extends clause is present, although specified in separate files the interfaces are both in the global scope and are merged by name into a single logical interface declaration that has both sets of members. (the same can be done for module scoped declarations with slightly different syntax)

By contrast, intersection types, as stored in a type declaration, are closed, not subject to merging.

There are many, many differences. You can read more about both constructs in the TypeScript Handbook. The Interfaces and Advanced Types section are particularly relevant.

Share Improve this answer   edited Jul 18, 2021 at 19:26 user avatar thanosades 322 silver badges33 bronze badges answered Oct 6, 2018 at 17:58 user avatar Aluan Haddad 26.3k66 gold badges6464 silver badges7777 bronze badges
  • 2 Great answer. Thanks for pointing out the difference in behaviour when 'overriding' properties, didn't know about that. That alone is a good reason to use types in certain use cases. Can you point out situations where interface merging is useful? Are there valid use cases when building applications (in other words: not libraries)?  – Willem-Aart  Oct 6, 2018 at 18:42 
  •   Willem Aart as you suggest, it is most useful for writing libraries, but what is an application if not a collection of libraries (including your own app). It can be extremely useful for applications as well. Ex: interface Object {hasOwnProperty<T, K extends string>(this: T, key: K): this is {[P in K]?}} which turns Object.prototype.hasOwnProperty into a type guard by introducing an additional, more specific signature for it. .  – Aluan Haddad  Oct 6, 2018 at 19:12 
  • 1 @AluanHaddad the StringToNumberConverter type should be instead named BidirectionalStringNumberConverter, correct? It seems like the other instances were possibly renamed...  – Karl Horky  Jul 4, 2019 at 19:56
  • 1 @NathanChappell thank you for catching that. I don't know when that broke. I've updated the example to make it compile, but it now requires a type assertion. I will look into this more.  – Aluan Haddad  Sep 22, 2020 at 8:37
  • 1 @AluanHaddad thanks. TS seems to be changing quite fast, so it's probably impossible to keep up with it (especially since they seem to have abandoned maintaining a specification...)  – Nathan Chappell  Sep 22, 2020 at 8:47
Show 3 more comments

标签:TypeScript,sheet,type,interfaces,share,extending,interface,data,se
来源: https://www.cnblogs.com/sexintercourse/p/16318398.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有