๐ Effective TypeScript ์ฑ ์ ์ฝ๊ณ ๊ณต๋ถํ ๋ด์ฉ์ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
๋ณ๊ฒฝ ๊ด๋ จ๋ ์ค๋ฅ ๋ฐฉ์ง๋ฅผ ์ํด readonly ์ฌ์ฉํ๊ธฐ
function arraySum(arr: number[]) {
let sum = 0, num;
while ((num = arr.pop()) !== undefined) {
sum += num;
}
return sum;
}
function printTriangles(n: number) {
const nums = [];
for (let i = 0; i < n; i++) {
nums.push(i);
console.log(arraySum(nums));
}
}
arraySum ํจ์
- ๋ฐฐ์ด ์์ ์ซ์๋ค์ ๋ชจ๋ ํฉ์น๊ณ
- ๊ณ์ฐ์ด ๋๋๋ฉด ์๋ ๋ฐฐ์ด์ด ์ ๋ถ ๋น๊ฒ ๋๋ค.
- ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐฐ์ด์ ๋ด์ฉ์ ๋ณ๊ฒฝํ ์ ์์ด์, ํ์ ์คํฌ๋ฆฝํธ ์ญ์ ์ค๋ฅ ์์ด ํต๊ณผํ ์ ์๋ค.
ํ์ง๋ง ์ค๋ฅ์ ๋ฒ์๋ฅผ ์ขํ๊ธฐ ์ํด, readonly
์ ๊ทผ ์ ์ด์๋ฅผ ์ฌ์ฉํ์ฌ
arraySum์ด ๋ฐฐ์ด์ ๋ณ๊ฒฝํ์ง ์๋๋ค๋ ์ ์ธ์ ํ๋ค.
function arraySum(arr: readonly number[]) {
let sum = 0, num;
while ((num = arr.pop()) !== undefined) {
// ~~~ 'pop' does not exist on type 'readonly number[]'
sum += num;
}
return sum;
}
readonly number[] ๋ โํ์ โ์ด๊ณ , number[] ์ ๊ตฌ๋ถ๋๋ ํน์ง๋ค์ด ์๋ค.
- ๋ฐฐ์ด์ ์์๋ฅผ ์ฝ์ ์ ์์ง๋ง, ์ธ ์๋ ์๋ค.
- length๋ฅผ ์ฝ์ ์ ์์ง๋ง, ๋ฐ๊ฟ ์ ์๋ค.
- ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ pop์ ๋น๋กฏํ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์๋ค.
number[]๋ readonly number[] ๋ณด๋ค ๊ธฐ๋ฅ์ด ๋ง๊ธฐ ๋๋ฌธ์, ์๋ธํ์ ์ด ๋๋ค.
๋ฐ๋ผ์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐฐ์ด์ readonly ๋ฐฐ์ด์ ํ ๋นํ ์ ์์ง๋ง, ๊ทธ ๋ฐ๋๋ ๋ถ๊ฐ๋ฅํ๋ค.
const a: number[] = [1, 2, 3];
const b: readonly number[] = a;
const c: number[] = b;
// ~ Type 'readonly number[]' is 'readonly' and cannot be
// assigned to the mutable type 'number[]'
๋งค๊ฐ๋ณ์๋ฅผ readonly๋ก ์ ์ธํ ๊ฒฝ์ฐ
- ํ์ ์คํฌ๋ฆฝํธ๋ ๋งค๊ฐ๋ณ์๊ฐ ํจ์ ๋ด์์ ๋ณ๊ฒฝ์ด ์ผ์ด๋๋์ง ์ฒดํฌํ๋ค.
- ํธ์ถํ๋ ์ชฝ์์๋ ํจ์๊ฐ ๋งค๊ฐ๋ณ์๋ฅผ ๋ณ๊ฒฝํ์ง ์๋๋ค๋ ๋ณด์ฅ์ ๋ฐ๊ฒ ๋๋ค.
- ํธ์ถํ๋ ์ชฝ์์ ํจ์๊ฐ readonly ๋ฐฐ์ด์ ๋งค๊ฐ๋ณ์๋ก ๋ฃ์ ์๋ ์๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์๋ ๋ช ์์ ์ผ๋ก ์ธ๊ธํ์ง ์๋ ํ, ํจ์๊ฐ ๋งค๊ฐ๋ณ์๋ฅผ ๋ณ๊ฒฝํ์ง ์๋๋ค๊ณ ๊ฐ์ ํ๋ค.
- ํ์ง๋ง ์๋ฌต์ ์ธ ๋ฐฉ๋ฒ์ ํ์ ์ฒดํฌ์ ๋ฌธ์ ๋ฅผ ์ผ์ผํด
- ๋ช ์์ ์ธ ๋ฐฉ๋ฒ์ด ์ข๋ค !
printTriangles๊ฐ ์ด์ ์ ๋๋ก ์๋ํ๋ค.
function arraySum(arr: readonly number[]) {
let sum = 0;
for (const num of arr) {
sum += num;
}
return sum;
}
> printTriangles(5)
0
1
3
6
10
ํจ์๊ฐ ๋งค๊ฐ๋ณ์๋ฅผ ๋ณ๊ฒฝํ์ง ์๋๋ค๋ฉด, readonly๋ก ์ ์ธํด์ผ ํ๋ค.
- ์ฅ์
- ๋์ ํ์ ์ผ๋ก ํธ์ถ ๊ฐ๋ฅ
- ์๋์น ์์ ๋ณ๊ฒฝ์ด ๋ฐฉ์ง๋๋ค.
- ์ง์ญ ๋ณ์์ ๊ด๋ จ๋ ๋ชจ๋ ์ข ๋ฅ์ ๋ณ๊ฒฝ ์ค๋ฅ ๋ฐฉ์ง ๊ฐ๋ฅ
- ๋จ์ (๊ตณ์ด ์ฐพ์๋ณด๋ ๋จ์ )
- ๋งค๊ฐ๋ณ์๊ฐ readonly๋ก ์ ์ธ๋์ง ์์ ํจ์๋ฅผ ํธ์ถํด์ผ ํ ๊ฒฝ์ฐ๋ ์๋ค.
- ํ์ง๋ง ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ์ ์ด๊ฐ ๊ฐ๋ฅํ๋ค๋ฉด readonly๋ก ์ ์ธํ๋ฉด ๋๋ค.
- ์ด๋ค ํจ์๋ฅผ readonly๋ก ๋ง๋ค๋ฉด, ๊ทธ ํจ์๋ฅผ ํธ์ถํ๋ ๋ค๋ฅธ ํจ์๋ ๋ชจ๋ readonly๋ก ๋ง๋ค์ด์ผ ํ๋ค.
- ์ธํฐํ์ด์ค๋ฅผ ๋ช ํํ ํ๊ณ ํ์ ์์ ์ฑ์ ๋์ผ ์ ์๊ธฐ ๋๋ฌธ์ ๊ผญ ๋จ์ ์ด๋ผ๊ณ ๋ณผ ์๋ ์๋ค.
- ๋งค๊ฐ๋ณ์๊ฐ readonly๋ก ์ ์ธ๋์ง ์์ ํจ์๋ฅผ ํธ์ถํด์ผ ํ ๊ฒฝ์ฐ๋ ์๋ค.
์ฐ์๋ ํ์ ๋ํด ๋น ์ค์ ๊ธฐ์ค์ผ๋ก ๋จ๋ฝ์ ๊ตฌ๋ถํ๋ ํ๋ก๊ทธ๋จ
function parseTaggedText(lines: string[]): string[][] {
const paragraphs: string[][] = [];
const currPara: string[] = [];
const addParagraph = () => {
if (currPara.length) {
paragraphs.push(currPara);
currPara.length = 0; // Clear the lines
}
};
for (const line of lines) {
if (!line) {
addParagraph();
} else {
currPara.push(line);
}
}
addParagraph();
return paragraphs;
}
[ [], [], [] ]
- ๋ฌธ์ ์
- ๋ณ์นญ๊ณผ ๋ณ๊ฒฝ์ ๋์์ ์ฌ์ฉํด ๋ฐ์
paragraphs.push(currPara);
- currPara์ ๋ด์ฉ์ด ์ฝ์ ๋์ง ์๊ณ ๋ฐฐ์ด์ ์ฐธ์กฐ๊ฐ ์ฝ์
- currPara์ ๋ค์ด ์๋ ๊ฐ์ด ์ง์์ง
- ๋์ผํ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ณ ์๋ paragraphs ์์์๋ ๋ณ๊ฒฝ์ด ๋ฐ์
โ ์ฆ, ์ ๋จ๋ฝ์ paragraphs์ ์ฝ์ ํ๊ณ ๋ฐ๋ก ์ง์๋ฒ๋ฆผ
- ๋ณ์นญ๊ณผ ๋ณ๊ฒฝ์ ๋์์ ์ฌ์ฉํด ๋ฐ์
currPara๋ฅผ readonly๋ก ์ ์ธํ์ฌ ์ด๋ฐ ๋์์ ๋ฐฉ์งํ ์ ์๋ค.
์ ์ธ์ ๋ฐ๊พธ๋ ์ฆ์ ์ฝ๋ ๋ด์์ ๋ช ๊ฐ์ง ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
function parseTaggedText(lines: string[]): string[][] {
const currPara: readonly string[] = [];
const paragraphs: string[][] = [];
const addParagraph = () => {
if (currPara.length) {
paragraphs.push(
currPara
// ~~~~~~~~ Type 'readonly string[]' is 'readonly' and
// cannot be assigned to the mutable type 'string[]'
);
currPara.length = 0; // Clear lines
// ~~~~~~ Cannot assign to 'length' because it is a read-only
// property
}
};
for (const line of lines) {
if (!line) {
addParagraph();
} else {
currPara.push(line);
// ~~~~ Property 'push' does not exist on type 'readonly string[]'
}
}
addParagraph();
return paragraphs;
}
currPara๋ฅผ let
์ผ๋ก ์ ์ธํ๊ณ ๋ณํ์ด ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ๋ ์ค๋ฅ๋ฅผ ์ก์ ์ ์๋ค.
let currPara: readonly string[] = [];
// ...
currPara = []; // ๋ฐฐ์ด์ ๋น์
// ...
currPara = currPara.concat([line]);
- concat ์ push ์ ๋ฌ๋ฆฌ ์๋ณธ์ ์์ ํ์ง ์๊ณ ์ ๋ฐฐ์ด์ ๋ฐํํ๋ค.
- ์ ์ธ๋ถ๋ฅผ const ์์ let์ผ๋ก ๋ณ๊ฒฝํ๊ณ readonly๋ฅผ ์ถ๊ฐํจ์ผ๋ก์จ ํ ์ชฝ์ ๋ณ๊ฒฝ ๊ฐ๋ฅ์ฑ์ ์ฎ๊น
- currPara ๋ณ์๋ ๊ฐ๋ฆฌํค๋ ๋ฐฐ์ด์ ์์ ๋กญ๊ฒ ๋ณ๊ฒฝํ ์ ์์ง๋ง
- ๋ฐฐ์ด ์์ฒด๋ ๋ณ๊ฒฝ ๋ถ๊ฐ
- currPara ๋ณ์๋ ๊ฐ๋ฆฌํค๋ ๋ฐฐ์ด์ ์์ ๋กญ๊ฒ ๋ณ๊ฒฝํ ์ ์์ง๋ง
์ฌ์ ํ ์กด์ฌํ๋ paragraphs์ ๋ํ ์ค๋ฅ๋ฅผ ๋ฐ๋ก์ก๋ ๋ฐฉ๋ฒ 3๊ฐ์ง
- currPara ๋ณต์ฌ๋ณธ ๋ง๋ค๊ธฐ
paragraphs.push([...currPara]);
- currPara๋ readonly๋ก ์ ์ง, ๋ณต์ฌ๋ณธ์ ์ํ๋๋๋ก ๋ณ๊ฒฝ์ด ๊ฐ๋ฅ
- paragraphs ๋ฅผ readonly string[] ์ ๋ฐฐ์ด๋ก ๋ณ๊ฒฝํ๊ธฐ
const paragraphs: (readonly string[])[] = [];
readonly string[][]์
- readonly ๋ฐฐ์ด์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐฐ์ด์ด ์๋๋ผ
- ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐฐ์ด์ readonly ๋ฐฐ์ด์ด๋ค
- ๋ฐฐ์ด์ readonly ์์ฑ์ ์ ๊ฑฐํ๊ธฐ ์ํด ๋จ์ธ๋ฌธ ์ฌ์ฉํ๊ธฐ
paragraphs.push(currPara as string[]);
- ๋ฐ๋ก ๋ค์ ๋ฌธ์ฅ์์ currPara๋ฅผ ์ ๋ฐฐ์ด์ ํ ๋นํจ
- ๊ณต๊ฒฉ์ ์ธ ๋จ์ธ๋ฌธ์ผ๋ก ๋ณด์ด์ง๋ ์์
- ๋ฐ๋ก ๋ค์ ๋ฌธ์ฅ์์ currPara๋ฅผ ์ ๋ฐฐ์ด์ ํ ๋นํจ
const dates: readonly Date[] = [new Date()];
dates.push(new Date());
// ~~~~ Property 'push' does not exist on type 'readonly Date[]'
dates[0].setFullYear(2037); // OK
- ๊ฐ์ฒด์ readonly ๋ฐฐ์ด์ด ์๋ค๋ฉด, ๊ทธ ๊ฐ์ฒด ์์ฒด๋ readonly๊ฐ ์๋๋ค.
interface Outer {
inner: {
x: number;
}
}
const o: Readonly<Outer> = { inner: { x: 0 }};
o.inner = { x: 1 };
// ~~~~ Cannot assign to 'inner' because it is a read-only property
o.inner.x = 1; // OK
type T = Readonly<Outer>;
// Type T = {
// readonly inner: {
// x: number;
// };
// }
- Readonly ์ ๋๋ฆญ์๋ ํด๋น๋๋ค.
- readonly ์ ๊ทผ์ ์ด์๋ x๊ฐ ์๋๋ผ inner์ ์ ์ฉ๋๋ ๊ฒ
ํ์ฌ ์์ ์๋ ๊น์(deep) readonly ํ์ ์ด ๊ธฐ๋ณธ์ผ๋ก ์ง์๋์ง ์์
Uploaded by N2T