@@ -5,21 +5,21 @@ permalink: /docs/handbook/unions-and-intersections.html
5
5
oneline : How to use unions and intersection types in TypeScript
6
6
---
7
7
8
- So far, the handbook has covered types which are atomic objects .
9
- However, as you model more types you find yourself looking for tools which let you compose or combine existing types instead of creating them from scratch .
8
+ ์ง๊ธ๊น์ง, ํธ๋๋ถ์ ์์ ๊ฐ์ฒด์ ํ์
๋ค์ ๋ค๋ค์์ต๋๋ค .
9
+ ํ์ง๋ง, ๋ ๋ง์ ํ์
์ ๋ชจ๋ธ๋งํ ์๋ก ์ฒ์๋ถํฐ ํ์
์ ๋ง๋ค์ด๋ด๊ธฐ๋ณด๋ค๋ ์ด๋ฏธ ์กด์ฌํ๋ ํ์
์ ๊ตฌ์ฑํ๊ฑฐ๋ ๊ฒฐํฉํ๋ ๋ฐฉ๋ฒ๋ค์ ์ฐพ๊ฒ ๋ ๊ฒ์
๋๋ค .
10
10
11
- Intersection and Union types are one of the ways in which you can compose types .
11
+ ๊ต์ฐจ ํ์
๊ณผ ์ ๋์ธ ํ์
์ ํ์
์ ๊ตฌ์ฑํ ์ ์๋ ๋ฐฉ๋ฒ ์ค ํ๋์
๋๋ค .
12
12
13
- # Union Types
13
+ # ์ ๋์ธ ํ์
( Union Types)
14
14
15
- Occasionally, you'll run into a library that expects a parameter to be either a ` number ` or a ` string ` .
16
- For instance, take the following function :
15
+ ๊ฐ๋, ` number ` ๋ ` string ` ์ ๋งค๊ฐ๋ณ์๋ก ๊ธฐ๋ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋๊ฐ ์์ต๋๋ค .
16
+ ์๋ฅผ ๋ค์ด, ๋ค์ ํจ์๋ฅผ ์ฌ์ฉํ ๋์
๋๋ค :
17
17
18
- ``` ts twoslash
18
+ ``` ts
19
19
/**
20
- * Takes a string and adds "padding" to the left .
21
- * If 'padding' is a string, then 'padding' is appended to the left side .
22
- * If 'padding' is a number, then that number of spaces is added to the left side .
20
+ * ๋ฌธ์์ด์ ๋ฐ๊ณ ์ผ์ชฝ์ "padding"์ ์ถ๊ฐํฉ๋๋ค .
21
+ * ๋ง์ฝ 'padding'์ด ๋ฌธ์์ด์ด๋ผ๋ฉด, 'padding'์ ์ผ์ชฝ์ ๋ํด์ง ๊ฒ์
๋๋ค .
22
+ * ๋ง์ฝ 'padding'์ด ์ซ์๋ผ๋ฉด, ๊ทธ ์ซ์๋งํผ์ ๊ณต๋ฐฑ์ด ์ผ์ชฝ์ ๋ํด์ง ๊ฒ์
๋๋ค .
23
23
*/
24
24
function padLeft(value : string , padding : any ) {
25
25
if (typeof padding === " number" ) {
@@ -31,33 +31,33 @@ function padLeft(value: string, padding: any) {
31
31
throw new Error (` Expected string or number, got '${padding }'. ` );
32
32
}
33
33
34
- padLeft (" Hello world" , 4 ); // returns " Hello world"
34
+ padLeft (" Hello world" , 4 ); // " Hello world"๋ฅผ ๋ฐํํฉ๋๋ค.
35
35
```
36
36
37
- The problem with ` padLeft ` in the above example is that its ` padding ` parameter is typed as ` any ` .
38
- That means that we can call it with an argument that's neither a ` number ` nor a ` string ` , but TypeScript will be okay with it .
37
+ ์ ์์ ์์ ` padLeft ` ์ ๋ฌธ์ ๋ ๋งค๊ฐ๋ณ์ ` padding ` ์ด ` any ` ํ์
์ผ๋ก ๋์ด์๋ค๋ ๊ฒ์
๋๋ค .
38
+ ์ฆ, ` number ` ๋ ` string ` ๋ ๋ค ์๋ ์ธ์๋ก ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค๋ ๊ฒ์ด๊ณ , TypeScript๋ ์ด๋ฅผ ๊ด์ฐฎ๋ค๊ณ ๋ฐ์๋ค์ผ ๊ฒ์
๋๋ค .
39
39
40
- ``` ts twoslash
40
+ ``` ts
41
41
declare function padLeft(value : string , padding : any ): string ;
42
- // ---cut ---
43
- // passes at compile time, fails at runtime .
42
+ // ---์๋ต ---
43
+ // ์ปดํ์ผ ํ์์๋ ํต๊ณผํ์ง๋ง, ๋ฐํ์์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค .
44
44
let indentedString = padLeft (" Hello world" , true );
45
45
```
46
46
47
- In traditional object-oriented code, we might abstract over the two types by creating a hierarchy of types .
48
- While this is much more explicit, it's also a little bit overkill .
49
- One of the nice things about the original version of ` padLeft ` was that we were able to just pass in primitives .
50
- That meant that usage was simple and concise .
51
- This new approach also wouldn't help if we were just trying to use a function that already exists elsewhere .
47
+ ์ ํต์ ์ธ ๊ฐ์ฒด์งํฅ ์ฝ๋์์, ํ์
์ ๊ณ์ธต์ ์์ฑํ์ฌ ๋ ํ์
์ ์ถ์ํํ ์ ์์ต๋๋ค .
48
+ ์ด๋ ๋ ๋ช
์์ ์ผ ์๋ ์์ง๋ง, ์กฐ๊ธ ๊ณผํ๋ค๊ณ ํ ์๋ ์์ต๋๋ค .
49
+ ๊ธฐ์กด ๋ฐฉ๋ฒ์ ` padLeft ` ์์ ์ข์ ์ ์ค ํ๋๋ ์์ ๊ฐ์ ๋จ์ง ์ ๋ฌํ ์ ์๋ค๋ ๊ฒ์
๋๋ค .
50
+ ์ฆ ์ฌ์ฉ๋ฒ์ด ๊ฐ๋จํ๊ณ ๊ฐ๊ฒฐํฉ๋๋ค .
51
+ ๋ํ ์ด ์๋ก์ด ๋ฐฉ๋ฒ์ ๋จ์ง ๋ค๋ฅธ ๊ณณ์ ์ด๋ฏธ ์กด์ฌํ๋ ํจ์๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ ๋ ๋์์ด ๋์ง ์์ต๋๋ค .
52
52
53
- Instead of ` any ` , we can use a _ union type _ for the ` padding ` parameter :
53
+ ` any ` ๋์ ์, _ ์ ๋์ธ ํ์
_์ ๋งค๊ฐ๋ณ์ ` padding ` ์ ์ฌ์ฉํ ์ ์์ต๋๋ค :
54
54
55
- ``` ts twoslash
55
+ ``` ts
56
56
// @errors: 2345
57
57
/**
58
- * Takes a string and adds "padding" to the left .
59
- * If 'padding' is a string, then 'padding' is appended to the left side .
60
- * If 'padding' is a number, then that number of spaces is added to the left side .
58
+ * ๋ฌธ์์ด์ ๋ฐ๊ณ ์ผ์ชฝ์ "padding"์ ์ถ๊ฐํฉ๋๋ค .
59
+ * ๋ง์ฝ 'padding'์ด ๋ฌธ์์ด์ด๋ผ๋ฉด, 'padding'์ ์ผ์ชฝ์ ๋ํด์ง ๊ฒ์
๋๋ค .
60
+ * ๋ง์ฝ 'padding'์ด ์ซ์๋ผ๋ฉด, ๊ทธ ์ซ์๋งํผ์ ๊ณต๋ฐฑ์ด ์ผ์ชฝ์ ๋ํด์ง ๊ฒ์
๋๋ค .
61
61
*/
62
62
function padLeft(value : string , padding : string | number ) {
63
63
// ...
@@ -66,14 +66,14 @@ function padLeft(value: string, padding: string | number) {
66
66
let indentedString = padLeft (" Hello world" , true );
67
67
```
68
68
69
- A union type describes a value that can be one of several types .
70
- We use the vertical bar (` | ` ) to separate each type, so ` number | string | boolean ` is the type of a value that can be a ` number ` , a ` string ` , or a ` boolean ` .
69
+ ์ ๋์ธ ํ์
์ ์ฌ๋ฌ ํ์
์ค ํ๋๊ฐ ๋ ์ ์๋ ๊ฐ์ ์๋ฏธํฉ๋๋ค .
70
+ ์ธ๋ก ๋ง๋ (` | ` )๋ก ๊ฐ ํ์
์ ๊ตฌ๋ถํ์ฌ, ` number | string | boolean ` ์ ๊ฐ์ ํ์
์ด ` number ` , ` string ` ํน์ ` boolean ` ์ด ๋ ์ ์์์ ์๋ฏธํฉ๋๋ค .
71
71
72
- ## Unions with Common Fields
72
+ ## ๊ณตํต ํ๋๋ฅผ ๊ฐ๋ ์ ๋์ธ ( Unions with Common Fields)
73
73
74
- If we have a value that is a union type, we can only access members that are common to all types in the union .
74
+ ์ ๋์ธ ํ์
์ธ ๊ฐ์ด ์์ผ๋ฉด, ์ ๋์ธ์ ์๋ ๋ชจ๋ ํ์
์ ๊ณตํต์ธ ๋ฉค๋ฒ๋ค์๋ง ์ ๊ทผํ ์ ์์ต๋๋ค .
75
75
76
- ``` ts twoslash
76
+ ``` ts
77
77
// @errors: 2339
78
78
79
79
interface Bird {
@@ -91,19 +91,19 @@ declare function getSmallPet(): Fish | Bird;
91
91
let pet = getSmallPet ();
92
92
pet .layEggs ();
93
93
94
- // Only available in one of the two possible types
94
+ // ๋ ๊ฐ์ ์ ์ฌ์ ์ธ ํ์
์ค ํ๋์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
95
95
pet .swim ();
96
96
```
97
97
98
- Union types can be a bit tricky here, but it just takes a bit of intuition to get used to .
99
- If a value has the type ` A | B ` , we only know for _ certain _ that it has members that both ` A ` _ and _ ` B ` have .
100
- In this example , ` Bird ` has a member named ` fly ` .
101
- We can't be sure whether a variable typed as ` Bird | Fish ` has a ` fly ` method .
102
- If the variable is really a ` Fish ` at runtime, then calling ` pet.fly() ` will fail .
98
+ ์ฌ๊ธฐ์ ์ ๋์ธ ํ์
์ ์ฝ๊ฐ ๊น๋ค๋ก์ธ ์ ์์ผ๋, ์ต์ํด์ง๋ ๋ฐ ์ฝ๊ฐ์ ์ง๊ด๋ง ์์ผ๋ฉด ๋ฉ๋๋ค .
99
+ ๋ง์ฝ ๊ฐ์ด ` A | B ` ํ์
์ ๊ฐ๊ณ ์์ผ๋ฉด, _ ํ์ ํ _ ์ ์๋ ๊ฒ์ ๊ทธ ๊ฐ์ด ` A ` _ ์ _ ` B ` ๋ ๋ค ๊ฐ์ง๊ณ ์๋ ๋ฉค๋ฒ๋ค์ ๊ฐ๊ณ ์๋ค๋ ๊ฒ๋ฟ์
๋๋ค .
100
+ ์ด ์์ ์์ , ` Bird ` ๋ ` fly ` ๋ผ๋ ๋ฉค๋ฒ๋ฅผ ๊ฐ๊ณ ์์ต๋๋ค .
101
+ ` Bird | Fish ` ๋ก ํ์
์ด ์ง์ ๋ ๋ณ์๊ฐ ` fly ` ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ํ์ ํ ์ ์์ต๋๋ค .
102
+ ๋ง์ฝ ๋ณ์๊ฐ ์ค์ ๋ก ๋ฐํ์์ ` Fish ` ์ด๋ฉด, ` pet.fly() ` ๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์ค๋ฅ์
๋๋ค .
103
103
104
- ## Discriminating Unions
104
+ ## ์ ๋์ธ ๊ตฌ๋ณํ๊ธฐ ( Discriminating Unions)
105
105
106
- A common technique for working with unions is to have a single field which uses literal types which you can use to let TypeScript narrow down the possible current type. For example, we're going to create a union of three types which have a single shared field .
106
+ ์ ๋์ธ์ ์ฌ์ฉํ๋ ๋ฐ ์์ด์ ์ผ๋ฐ์ ์ธ ๊ธฐ์ ์ TypeScript๊ฐ ํ์ฌ ๊ฐ๋ฅํ ํ์
์ถ๋ก ์ ๋ฒ์๋ฅผ ์ขํ๋๊ฐ๊ฒ ํด์ค ์ ์๋ ๋ฆฌํฐ๋ด ํ์
์ ๊ฐ๋ ๋จ์ผ ํ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, ํ๋์ ๊ณตํต ํ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ ์ธ ๊ฐ์ง ํ์
์ ์ ๋์ธ์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค .
107
107
108
108
``` ts
109
109
type NetworkLoadingState = {
@@ -124,45 +124,15 @@ type NetworkSuccessState = {
124
124
};
125
125
};
126
126
127
- // Create a type which represents only one of the above types
128
- // but you aren't sure which it is yet .
127
+ // ์ ํ์
๋ค ์ค ๋จ ํ๋๋ฅผ ๋ํํ๋ ํ์
์ ๋ง๋ค์์ง๋ง,
128
+ // ๊ทธ๊ฒ์ด ๋ฌด์์ ํด๋นํ๋์ง ์์ง ํ์คํ์ง ์์ต๋๋ค .
129
129
type NetworkState =
130
130
| NetworkLoadingState
131
131
| NetworkFailedState
132
132
| NetworkSuccessState ;
133
133
```
134
134
135
- <style type =" text/css " >
136
- .markdown table .tg {
137
- border-collapse :collapse ;
138
- width : 100% ;
139
- text-align : center ;
140
- display : table ;
141
- }
142
-
143
- .tg th {
144
- border-bottom : 1px solid black ;
145
- padding : 8px ;
146
- padding-bottom : 0 ;
147
- }
148
-
149
- .tg tbody , .tg tr {
150
- width : 100% ;
151
- }
152
-
153
- .tg .highlight {
154
- background-color : #F3F3F3 ;
155
- }
156
-
157
- @media (prefers-color-scheme: dark) {
158
- .tg .highlight {
159
- background-color : #424242 ;
160
- }
161
- }
162
-
163
- </style >
164
-
165
- All of the above types have a field named ` state ` , and then they also have their own fields:
135
+ ์ ํ์
๋ค์ ๋ชจ๋ ` state ` ๋ผ๋ ํ๋๋ฅผ ๊ฐ๊ณ ์์ผ๋ฉฐ, ๊ทธ๋ค ๊ฐ์๋ง์ ํ๋๋ ๊ฐ๊ณ ์์ต๋๋ค:
166
136
167
137
<table class =' tg ' width =" 100% " >
168
138
<tbody >
@@ -184,9 +154,9 @@ All of the above types have a field named `state`, and then they also have their
184
154
</tbody>
185
155
</table >
186
156
187
- Given the ` state ` field is common in every type inside ` NetworkState ` - it is safe for your code to access without an existence check .
157
+ ` state ` ํ๋๊ฐ ` NetworkState ` ์์ ๋ชจ๋ ํ์
์ ๊ณตํต์ผ๋ก ์กด์ฌํ๋ค๋ ์ ์ ์๋ค๋ฉด - ์กด์ฌ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ์ง ์๊ณ ๋ ์ ๊ทผํ ์ ์์ต๋๋ค .
188
158
189
- With ` state ` as a literal type, you can compare the value of ` state ` to the equivalent string and TypeScript will know which type is currently being used .
159
+ ๋ฆฌํฐ๋ด ํ์
์ผ๋ก์ ` state ` ๋ฅผ ๊ฐ๊ณ ์๋ค๋ฉด, ` state ` ์ ๊ฐ์ ๋์ํ๋ ๋์ผํ ๋ฌธ์์ด๊ณผ ๋์กฐ๋๊ณ TypeScript๋ ํ์ฌ ์ด๋ค ํ์
์ด ์ฌ์ฉ๋๊ณ ์๋์ง ์ ๊ฒ์
๋๋ค .
190
160
191
161
<table class =' tg ' width =" 100% " >
192
162
<tbody >
@@ -203,9 +173,9 @@ With `state` as a literal type, you can compare the value of `state` to the equi
203
173
</tbody>
204
174
</table >
205
175
206
- In this case, you can use a ` switch ` statement to narrow down which type is represented at runtime:
176
+ ์ด ๊ฒฝ์ฐ, ๋ฐํ์์ ๋ํ๋๋ ํ์
์ ๋ฒ์๋ฅผ ์ขํ๊ธฐ ์ํ์ฌ ` switch ` ๋ฌธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
207
177
208
- ``` ts twoslash
178
+ ``` ts
209
179
// @errors: 2339
210
180
type NetworkLoadingState = {
211
181
state: " loading" ;
@@ -224,28 +194,28 @@ type NetworkSuccessState = {
224
194
summary: string ;
225
195
};
226
196
};
227
- // ---cut ---
197
+ // ---์๋ต ---
228
198
type NetworkState =
229
199
| NetworkLoadingState
230
200
| NetworkFailedState
231
201
| NetworkSuccessState ;
232
202
233
203
function networkStatus(state : NetworkState ): string {
234
- // Right now TypeScript does not know which of the three
235
- // potential types state could be .
204
+ // ํ์ฌ TypeScript๋ ์
์ค ์ด๋ค ๊ฒ์ด
205
+ // state๊ฐ ๋ ์ ์๋ ์ ์ฌ์ ์ธ ํ์
์ธ์ง ์ ์ ์์ต๋๋ค .
236
206
237
- // Trying to access a property which isn't shared
238
- // across all types will raise an error
207
+ // ๋ชจ๋ ํ์
์ ๊ณต์ ๋์ง ์๋ ํ๋กํผํฐ์ ์ ๊ทผํ๋ ค๋ ์๋๋
208
+ // ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค.
239
209
state .code ;
240
210
241
- // By switching on state, TypeScript can narrow the union
242
- // down in code flow analysis
211
+ // state์ swtich๋ฌธ์ ์ฌ์ฉํ์ฌ, TypeScript๋ ์ฝ๋ ํ๋ฆ์ ๋ถ์ํ๋ฉด์
212
+ // ์ ๋์ธ ํ์
์ ์ขํ๋๊ฐ ์ ์์ต๋๋ค.
243
213
switch (state .state ) {
244
214
case " loading" :
245
215
return " Downloading..." ;
246
216
case " failed" :
247
- // The type must be NetworkFailedState here ,
248
- // so accessing the `code` field is safe
217
+ // ์ฌ๊ธฐ์ ํ์
์ NetworkFailedState์ผ ๊ฒ์ด๋ฉฐ ,
218
+ // ๋ฐ๋ผ์ `code` ํ๋์ ์ ๊ทผํ ์ ์์ต๋๋ค.
249
219
return ` Error ${state .code } downloading ` ;
250
220
case " success" :
251
221
return ` Downloaded ${state .response .title } - ${state .response .summary } ` ;
@@ -263,7 +233,7 @@ That means an object of this type will have all members of all three types.
263
233
264
234
For example, if you had networking requests with consistent error handling then you could separate out the error handling into it's own type which is merged with types which correspond to a single response type.
265
235
266
- ``` ts twoslash
236
+ ``` ts
267
237
interface ErrorHandling {
268
238
success: boolean ;
269
239
error? : { message: string };
@@ -297,7 +267,7 @@ const handleArtistsResponse = (response: ArtistsResponse) => {
297
267
298
268
Intersections are used to implement the [ mixin pattern] ( /docs/handbook/mixins.html ) :
299
269
300
- ``` ts twoslash
270
+ ``` ts
301
271
class Person {
302
272
constructor (public name : string ) {}
303
273
}
@@ -333,4 +303,4 @@ function extend<First extends {}, Second extends {}>(
333
303
334
304
const jim = extend (new Person (" Jim" ), ConsoleLogger .prototype );
335
305
jim .log (jim .name );
336
- ```
306
+ ` ` ` -
0 commit comments