( << Back) TypeVsInterface.ts
1: console.log(`
2: --- 1 --- interface vs type
3: `)
4:
5: //interface vs types (2018)
6: //https://stackoverflow.com/questions/37233735/interfaces-vs-types-in-typescript/52682220#52682220
7: //
8: //Type Interface
9: //✅ ✅ Can describe functions
10: //✅ ✅ Can describe constructors
11: //✅ ✅ Can describe tuples
12: //✅ ✅ Can be mapped over with mapped types
13: //✅ ⚠️ Can intersect another one of its kind
14: //✅ 🚫 Can create a union with another one of its kind
15: //✅ 🚫 Can be used to create mapped types
16: //✅ 🚫 Expands in error messages and logs
17: //⚠️ ✅ Classes can implement it (implements)
18: //⚠️ ✅ Can be recursive
19: //⚠️ ✅ Interfaces can extend it
20: //🚫 ✅ Classes can extend it
21: //🚫 ✅ Can be augmented
22: //
23: //for 2021 version (summary)
24: //
25: //When to use type:
26: //
27: // Use type when defining an alias for primitive types (string, boolean, number, bigint, symbol, etc)
28: // Use type when defining tuple types
29: // Use type when defining function types
30: // Use type when defining a union
31: // Use type when trying to overload functions in object types via composition
32: // Use type when needing to take advantage of mapped types
33: //
34: //When to use interface:
35: //
36: // Use interface for all object types where using type is not required (see above)
37: // Use interface when you want to take advantage of declaration merging.
38:
39:
40: //Only type can be used to alias a primitive:
41: type Primitive = number | string | boolean | null | undefined
42: type Nullish = null | undefined;
43: type Fruit = 'apple' | 'pear' | 'orange';
44: type Num = number | bigint;
45:
46: //Tuples can only be typed via the type keyword:
47: type row = [colOne: number, colTwo: string];
48:
49: //Functions can be typed by both the type and interface keywords:
50: interface Point1 {
51: x: number;
52: y: number;
53: }
54:
55: interface SetPoint1 {
56: (x: number, y: number): void;
57: }
58:
59: type Point2 = {
60: x: number;
61: y: number;
62: };
63:
64: type SetPoint2 = (x: number, y: number) => void;
65:
66: //Union types can only be achieved with the type keyword:
67: type Vegetable = 'broccoli' | 'carrot' | 'lettuce';
68: type HealthyFoods = Fruit | Vegetable;
69:
70: //types and inerface composition vith the same JS key/value , declaration can Merging (see above example of hacking keyof)
71:
72: interface NumLogger {
73: log: (val: number) => void;
74: }
75: type StrAndNumLogger1 = NumLogger & {
76: log: (val: string) => void;
77: }
78:
79: const logger: StrAndNumLogger1 = {
80: log: (val: string | number) => console.log(val)
81: }
82:
83: logger.log(1)
84: logger.log('hi')
85:
86: console.log(`
87: --- 2 --- Use the type when you are transforming multiple types into a single generic type. Nullable<T> , NonNull<T>, Never type and ternary operator with types
88: `)
89:
90: //Generic Transformations. Use the type when you are transforming multiple types into a single generic type.
91: type Nullable<T> = T | null | undefined
92: type NonNull<T> = T extends (null | undefined) ? never : T
93:
94: console.log(`
95: --- 3 --- Mapped object types possible obly with Type
96: `)
97:
98: type FruitCount = {
99: [key in Fruit]: number;
100: }
101:
102: const fruits: FruitCount = {
103: apple: 2,
104: orange: 3,
105: pear: 0
106: };
107:
108: console.log(fruits)
109:
110: console.log(`
111: --- 4 --- The key difference pointed out in the documentation is that Interface can be reopened to add new property but Type alias cannot be reopened to add new property
112: `)
113:
114: interface I1 {
115: name: string
116: }
117:
118: interface I1 {
119: age: number
120: }
121:
122: let var1: I1 = { name: 'a', age: 10 }
123: console.log(var1)
124:
125: console.log(`
126: --- 5 --- Difference types and intefaces in indexing. https://stackoverflow.com/questions/37233735/interfaces-vs-types-in-typescript
127: `)
128:
129: interface MyInterface {
130: foobar: string;
131: }
132:
133: type MyType = {
134: foobar: string;
135: }
136:
137: const exampleInterface: MyInterface = { foobar: 'hello world' };
138: const exampleType: MyType = { foobar: 'hello world' };
139:
140: //Construct a type with a set of properties K of type T
141: //type Record<K extends string | number | symbol, T> = { [P in K]: T; }
142: let record: Record<string, string> = {};
143:
144: record = exampleType; // Compiles
145: //record = exampleInterface; // Index signature is missing
146:
147: console.log(`
148: --- 6 --- Index signature is missing in type (only on interfaces, not on type alias) https://github.com/microsoft/TypeScript/issues/15300
149: `)
150:
151: interface IndexType {
152: [key: string]: string;
153: }
154:
155: interface doesNotWork {
156: hola: string;
157: }
158: type doWorks = { hola: string };
159:
160: let y: IndexType;
161:
162: const correctA = { hola: "hello" };
163: const correctB: doWorks = { hola: "hello" };
164:
165: //error should be assignable to y
166: const error: doesNotWork = { hola: "hello " };
167:
168: y = correctA;
169: y = correctB;
170: /**
171: /* y = error; //Index signature is missing in type 'doesNotWork'
172: */
173: y = { ...error }; //workaround but not equivalent since the instance is not the same
174: console.log(y, correctA, correctB, error)
175:
176: console.log(`
177: --- 7 --- Difference in evaluation
178: `)
179:
180: /**
181: * When FirstLevelType is interface
182: */
183:
184: interface FirstLevelType1<A, Z> {
185: _: "typeCheck";
186: };
187:
188: type TestWrapperType1<T, U> = FirstLevelType1<T, U>;
189:
190:
191: const a1: TestWrapperType1<{ cat: string }, { dog: number }> = {
192: _: "typeCheck",
193: };
194:
195: // { cat: string; }
196: type ExtendFirst1 = typeof a1 extends FirstLevelType1<infer T, infer _>
197: ? T
198: : "not extended";
199:
200: const a11: ExtendFirst1 = { cat: '' }
201:
202: console.log(a1, a11)
203:
204: /**
205: * When FirstLevelType is type
206: */
207: type FirstLevelType2<A, Z> = {
208: _: "typeCheck";
209: };
210:
211: type TestWrapperType2<T, U> = FirstLevelType2<T, U>;
212:
213:
214: const a2: TestWrapperType2<{ cat: string }, { dog: number }> = {
215: _: "typeCheck",
216: };
217:
218: // unknown
219: type ExtendFirst2 = typeof a2 extends FirstLevelType2<infer T, infer _>
220: ? T
221: : "not extended";
222:
223: const a21: ExtendFirst2 = { cat: '' }
224:
225: console.log(a2, a21)
Comments (
)
Link to this page:
http://www.vb-net.com/TypescriptLearningStartPoint/TypeVsInterface.htm
|