โ ์ฑ ๋ณด๊ณ ๋ฐ๋ผ ํด๋ ์๋๋ค๊ณ , ์ค์ค๋ก ์์ฑ ํ์ง ๋ง๋ผ.
์ง์ง ๋ฉ์ฒญ์ด๋ค์ ์ผ๋ฐ์ธ๋ค์ด ์ฌ์ฉํ ์ ์๋๋ก ํ๋์จ์ด์ ์ํํธ์จ์ด๋ฅผ ๋ง๋ ์ฌ๋๋ค์ด๋ค. ์ฌ๋๋ค์ด ์ปดํจํฐ๋ฅผ ์ฌ์ฃผ๋๋ฐ๋ ๋ง์ด๋ค.
์ฐ๋ฆฌ๋ ๊ทธ๋ค์ ์ปดํจํฐ ์ ๋ฌธ๊ฐ๋ผ๊ณ ๋ถ๋ฅธ๋ค. โ- Walter Mossberg
์ ๋ช ํ ํ ํฌ ์ ๋๋ฆฌ์คํธ

Non-null assertion operator
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ํฌํจํ ๋๋ถ๋ถ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ๋๋ํ(!)๋ ์ฃผ๋ก False๋ฅผ ์๋ฏธํ๋ ์ฐ์ฐ์๋ก ์ฌ์ฉ๋๋ค.
ํ์ง๋ง ํ์ ์คํฌ๋ฆฝํธ์์ ๋ณ์ ์์ด ์๋, ๋ค์ ๋๋ํ(!)๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ๋ฐํ ์ฉ๋๋ก ์ฌ์ฉํ ์ ์๋๋ฐ, ํผ์ฐ์ฐ์๊ฐ Nullish(null์ด๋ undefined) ๊ฐ์ด ์๋์ ๋จ์ธํ ์ ์๋ค.
์ด๋ฅผ Null์ด ์๋ ๋จ์ธ ์ฐ์ฐ์(Non-null assertion operator) ๋๋ ํ์ ํ ๋น ์ด์ ์ (Definite Assignment Assertions) ์ด๋ผ๊ณ ๋ ๋ถ๋ฅธ๋ค. Null์ด ์๋ ์ด์ ์ ์ฐ์ฐ์๋ ํผ์ฐ์ฐ์๊ฐ null์ด ์๋๋ผ๊ณ ์ปดํ์ผ๋ฌ์๊ฒ ์ ๋ฌํ์ฌ ์ผ์์ ์ผ๋ก Null ์ ์ฝ์กฐ๊ฑด์ ์ํ์ํจ๋ค.
๋น์ต ๋ฌด์จ๋ง์ธ์ง ๋ชจ๋ฅผ๊ฒ์ด๋ค. ๐ช ์ดํด๋ฅผ ๋๊ธฐ์ํด ๋ค์ ์ฝ๋๋ฅผ ์ดํด๋ณด์.
๋ค์๊ณผ ๊ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์๋ค. menu-item ์ด๋ผ๋ ์๋ฆฌ๋จผํธ๋ฅผ ๋ถ๋ฌ์ ๊ทธ์ ์์ฑ์ธ innerHTML์ ๊ฐ์ ธ์จ๋ค.
ํ์ง๋ง ๋ง์ผ menu-item ์ด๋ผ๋ ์๋ฆฌ๋จผํธ๊ฐ ์กด์ฌํ์ง ์์๋ ์๋ฌด๋ฆฌ ์๋ฐ์คํฌ๋ฆฝํธ๋ผ ํด๋ ๋ฐ๋ก ์๋ฌ๋ฅผ ๋ด๋ฟ๋๋ค.
๊ทธ๋์ ๋ณดํต ?. ์ฐ์ฐ์๋ฅผ ํตํด ํด๊ฒฐํ๋ค. (๊ฐ์ undefined์ง๋ง ์๋ฌ๋ ์๋๋ค)
document.querySelector('.menu-item').innerHTML;
// menu-item ์๋ฆฌ๋จผํธ๊ฐ ์์ ๊ฒฝ์ฐ๋ฅผ ๋๋นํด ์ด๋ฐ์์ผ๋ก && ์ฐ์ฐ์๋ฅผ ์ฐ๊ฑฐ๋
document.querySelector('.menu-item') && document.querySelector('.menu-item').innerHTML
// ๋ค์๊ณผ ๊ฐ์ด ? ๋ก ํด๊ฒฐํ ์ ์๋ค.
document.querySelector('.menu-item')?.innerHTML;

๊ทธ๋ผ ํ์ ์คํฌ๋ฆฝํธ๋ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊น?
ํ์ ๋จ์ธ ์ ์ด์ฉํด ํด๊ฒฐํ๋๊ฐ ์๋๋ฉด ์์ ์๋ฐ์คํฌ๋ฆฝํธ์์ ?. ์ฐ์ฐ์๋ฅผ ์ผ๋ฏ์ด, ๋ฌผ์ํ๋ฅผ ๋๋ํ๋ก ๊ณ ๋๋ก ๋ฐ๊ฟ !. ์ฌ์ฉํ๋ฉด ํด๊ฒฐํ ์ ์๋ค.
์ฆ, menu-item ์๋ฆฌ๋จผํธ ๋ถ๋ฌ์จ ๋์์ด null์ด๋ undefined๊ฐ ์๋์ ๋จ์ธํ ์ ์์๋ ๋น๋ก์ innerHTML์ ์ ๊ทผํ๋ผ๋ ์๋ฏธ์ธ ๊ฒ์ด๋ค.
// Error - TS2531: Object is possibly 'null'.
document.querySelector('.menu-item').innerHTML;
// ํ์
๋จ์ธ (Type assertion)
(document.querySelector('.menu-item') as HTMLDivElement).innerHTML;
(<HTMLDivElement>document.querySelector('.menu-item')).innerHTML;
// Non-null assertion operator
document.querySelector('.menu-item')!.innerHTML;
์ธํฐํ์ด์ค๋ก ๋ค๋ฅธ ์์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
interface nameObject {
firstName: string;
lastName: string | null;
}
let obj: nameObject = {
firstName: "Kang",
lastName: null
};
// lastName ํค์ ๊ฐ์ด string์ด๋ null์ด ๋ค์ด์ฌ์ ์์ง๋ง ๋ง์ผ ์์ ๊ฐ์ด null์ด ๋ค์ด์ ๋ฒ๋ฆฌ๋ฉด toString์ ์คํํ ์ ์๊ธฐ์
// tsc ์ปดํ์ผ๋ฌ๊ฐ ๋ฏธ๋ฆฌ ๊ฒฝ๊ณ ๋ฅผ ๋์์ค๋ค !!
console.log(obj.lastName.toString());

๊ดํ ํ์ ๊ฐ๋๋ ์กฐ๊ฑด์ ์กฐ๊ฑด๋ฌธ์ ์์ฐ์ง๋ง๊ณ ๊ฐ๋จํ๊ฒ !. ์ฐ์ฐ์(Non null)์ ์ถ๊ฐํด ํด๊ฒฐ์ด ๊ฐ๋ฅํ๋ค.
console.log(obj.lastName!.toString());
non-null ๋จ์ธ ์ฐ์ฐ์๋ฅผ ๋ณด๋ค ์ดํด๋ฅผ ๋๊ธฐ ์ํด ์์ฒ๋ผ ์ค๋ช ํ์ง๋ง, ์ฌ์ค ํ์ ์คํฌ๋ฆฝํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ฌธ๋ฒ์ ๋ชจ๋ ํฌํจํ๊ธฐ ๋๋ฌธ์ ์ต์ ๋ ์ฒด์ด๋ (?.)์ ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
๋ค๋ง, ์ต์ ๋ ์ฒด์ด๋ (?.) ๊ณผ ๋จ์ธ ์ฐ์ฐ์ (!) ๋ ์๋ก ๋ปํ๋ ๋ฐ๊ฐ ๋ค๋ฅด๋ ์ ์ํ์.
Definite Assignment Assertions
ํ์ ํ ๋น ๋จ์ธ(Definite Assignment Assertions)์ ์์ํ ์ฉ์ด์ผ์๋ ์์ํ ๋ฐ, ๊ฐ๋จํ ๋งํ๋ฉด ๋ณ์์ ๊ฐ์ด ๋ฌด์กฐ๊ฑด ํ ๋น๋์ด์๋ค๊ณ ์ปดํ์ผ๋ฌ์๊ฒ ์ ๋ฌํ์ฌ ๊ฐ์ด ์์ด๋ ๋ณ์ ๋๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋ค๊ณ ๋จ์ธํ๋ ๊ฒ์ด๋ค.
๋ค์๊ณผ ๊ฐ์ด, menu ๋ณ์์ ์ค์ ๋ก ์๋ฆฌ๋จผํธ๊ฐ ์์์ง ์์์ง ๋จ์ธ ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ค์ menu.innerHTML ์ฝ๋๋ ์๋ฌ๊ฐ ๋๊ฒ ๋๋ค.
const menu = document.querySelector('.menu-item');
menu.innerHTML; // Error

์ด๋ด๋๋ ๊ตญ๋ฃฐ์ ์ผ๋ก ์กฐ๊ฑด๋ฌธ์ ์ด์ฉํด ํํฐ๋ง ํ๊ฑฐ๋, ์๋๋ฉด ํ์ฅ ํ ๋น ๋จ์ธ(!) ์ ํตํด ๊ตฌํ์ด ๊ฐ๋ฅํ๋ค.
const menu = document.querySelector('.menu-item');
if(menu) {
menu.innerHTML;
}
const menu = document.querySelector('.menu-item')!; // ๋ณ์ ์ฐ์ธก์ ๋๋ํ๋ฅผ ๋ถ์ธ๋ค.
menu.innerHTML; // Error
์ด๋ฌํ ํ์๋ ์ปดํ์ผ๋ฌ์๊ฒ "๋ณ์ n๋ ๊ฐ์ด ๋ฌด์กฐ๊ฑด ๊ฐ์ด ํ ๋น๋์ด ์๋ค๋ ๊ฒ์ ๋ด ์๋ชจ๊ฐ์ง๋ฅผ ๊ฑด๋ค."๋ผ๊ณ ๋จ์ธํ ๊ฒ์ด๋ค.
์ปดํ์ผ๋ฌ๋ ์๊ท๊ฐ ์๋ ์ซ๋ณด์ด๊ธฐ ๋๋ฌธ์ "๋ค ๋๋ ๋ง์ ๋ฐ๋ฅด๊ฒ ์ต๋๋ค. ๋์ ์๋ฌ๋ ๋๋์ด ๋ค ์ฑ ์์ง์ธ์." ๋ผ๊ณ ํ๋ฉฐ ์๋ฌ ํ์์ค์ ์์ ์ฃผ๋ ๊ฒ์ด๋ค.
์ฆ, ํ์ ํ ๋น ๋จ์ธ์ ๋ณ์์ ๊ฐ์ด ๋ฌด์กฐ๊ฑด ์กด์ฌํ๋ค๋ ํ์ ์ด ์์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ฉด ๋๋ค.
ํ์ง๋ง ๊ฐ๋ ์ฑ์ ์ํด ์ต๋ํ ๋๋ํ ๋์ if๋ฌธ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฑธ ์ถ์ฒํ๋ค
# ์ฐธ๊ณ ์๋ฃ
https://heropy.blog/2020/01/27/typescript/
์ด์ฌ์น ํ์ ์คํฌ๋ฆฝํธ ์์ํ๊ธฐ
์ ๋ก์ด ํ์ ์คํฌ๋ฆฝํธ ์ฌ์ธ์
์ด ๊ธ์ด ์ข์ผ์ จ๋ค๋ฉด ๊ตฌ๋ & ์ข์์
์ฌ๋ฌ๋ถ์ ๊ตฌ๋
๊ณผ ์ข์์๋
์ ์์๊ฒ ํฐ ํ์ด ๋ฉ๋๋ค.