해결된 질문
작성
·
158
·
수정됨
1
안녕하세요,
강좌, "조건 타입으로 Object 키 새로 만들기 "부분에서 'as' 용도에 대해서 문의 드립니다.
(코드의 의미는 이해했습니다!)
[K in keyof T as K extends ${string}${'id'|'Id'} ? K : never ] : T[K]
타입스크립트에서 as가, 기존의 타입을 다른 어떤 타입의 것으로 '강제'하는 것으로 알고 있습니다.
(as는 쓰면 안되는 그런것으로,,,)
그런 용도로 알고 있다 보니,
강좌에서 'as'의 쓰임새가 제가 알고 있는 것과 동일한 것인지 문의드립니다.
추측컨대, as의 쓰임새가 타입을 다른 것으로 강제, 즉 변환하는 것 이외에
어떤 무엇을 지칭하는 용도로도 사용된 듯한 추측이 들어서 질문합니다.
위 코드에서 as는, K의 내용을 가리킨다 혹은 ~와 같은 맥락 이라는 as 영어단어와 비슷한 의미로 추측됩니다.
위 코드가 어떤 의미인지 알게 되면, 이후에 as를 자유롭게 사용할 수 있을 것 같습니다.
막상 as를 포함해서 코드를 적을 수 없을 꺼 같아서요
(=as를 빼먹고 코드를 적을 것 같아서요)
이전 강좌에서도 종종 'as'가 위와 같은 용도로 사용하신건지요?
그 쓰임새와 의미에 대해서 정리 부탁드릴 수 있을까요?
답변 1
1
안녕하세요 프린이님. 좋은 질문입니다.
"조건 타입으로 Object 키 새로 만들기 "부분에서 'as' 는 알고 계신
타입스크립트에서 as가, 기존의 타입을 다른 어떤 타입의 것으로 '강제'하는 것으로 알고 있습니다.
과 조금 다른 기능입니다. 새로운 Object의 Key를 만드는 컨텍스트에서 사용되는 as
는 as
뒤의 결과(타입 스페이스의 조건문, 즉 ${string}${'id'|'Id'}
의 패턴을 따르면 K를 새로운 object의 키로 사용하고 아니라면 그 키를 버린다)를 Object의 Key로 사용하겠다라는 의미입니다.
따라서 추측하신대로
as의 쓰임새가 타입을 다른 것으로 강제, 즉 변환하는 것 이외에 어떤 무엇을 지칭하는 용도로도 사용된 듯한 추측이 들어서 질문합니다.
무언가를 지칭한다기보다는 Key를 변형하는 용도로 사용했습니다.
그리고 다른 용도를 이미 알고 계신데 타입을 강제하는 역할도 합니다.
Object key를 변형하는 케이스 외 알고 계신 특정 언어로 강제하는 기능이 있습니다. 전 강제한다는 표현이 조금 모호하다고 생각하는데 그 이유는
type Foo = number
type Boo = string
const fooOrBoo: Foo | Boo = 1 as object; // type error!
const fooOrBoo: Foo | Boo = 1 as unknown as object; // ok!
위 같은 코드가 있다고 했을 때 강제한다고 하면 타입에러가 발생하면 안되는데 타입에러가 발생합니다.
그래서 as
를 어떤 타입이 있을 때 그 타입에 가깝게 변환한다고 말할 수 있을 것 같은데요. 엄밀하게 말씀드리면
as 뒤에 있는 타입으로 변형할 수 있는데 조건은 뒤에 있는 타입의 조건은 as 앞에 있는 타입보다 좀 더 구체적이거나 느슨한 것으로 변경할 수 있다
입니다.
하나의 예시를 보면
type Foo = {a: 1}
type Boo = {a: 1, b:2}
const fooOrBoo: Foo | Boo = {a: 1, b: 2} as Foo;
const fooOrBoo2: Foo | Boo = {a: 1} as Boo;
fooOrBoo
나 fooOrBoo2
둘 다 타입에러가 발생하지 않습니다.
첫번째 fooOrBoo
는 as
뒤에 있는 타입이 앞에 {a: 1, b: 2}
보다 타입이 덜 구체적입니다. 반면에
밑의 경우엔 as
뒤에 있는 타입이 앞에 있는 타입보다 좀 더 구체적입니다.
이런 목적으로 사용하는 것이 as
이고 타입을 정확히 작성할 수 있으면 그렇게 작성해야 하겠지만 이런 비슷한 상황에선 as
를 사용할 수 있다고 생각합니다.
제가 요즘 조금 바빠서 생각만 하고 못 올리고 있는 주제가 있는데 마무리 되면 as
와 satisfies
에 대해서 강의를 업데이트 하도록 하겠습니다.
1. 어떤 대상을 암시적?으로 가리키면서(여기에서 T타입의 key를 의미),
뒤에 조건식의 내용을 '이어'가게 해주는 '의미적 사다리?" 라고
애매하게?나마 이해해도 될까요?
네 맞습니다. 정확하게는 "내가 T를 object의 키로 사용을 안하고 as 뒤에서 만들어지는 것으로 사용할거야" 라고 이해하시면 되겠습니다. 이 맥락에서 제대로 이해했는지 아래에서 Test의 타입은 어떻게 될까요?
const obj = {a: 1, b: 2}
type Test = {
[K in keyof typeof obj as `${K}1`]: number
}
const obj = {a: 1, b: 2}
type Test = {
[K in keyof typeof obj as `${K}1`]: number
}
//이거 아닐까요??
type Test = {a1:number, b1:number}
구문별로 정리해봤습니다!
틀린부분 있을까요??
typeof obj // 값 obj의 타입을 구하기(값의 영역에서 타입의 영역을 구함,즉 obj의 타입을 구함)- 값의 영역과 타입의 영역
keyof typeof obj // 그 타입의 key들의 유니온을 구함(a | b)
K in keyof typeof obj // key들의 유니온 배열 중 순환하는 k는 a 혹은 b
..중략.. as `${K}1` // 그 k는(as) a1 혹은 b1, 문자열로 타입변환,
[K in keyof typeof obj as `${K}1`] // 값 obj의 타입의 키, a 혹은 b 를 문자역 a1 혹은 b1으로 한다(하고)
..중략 : number // 문자열 a1 혹은 문자열 b1의 타입은 각각 number 다
좀 더 구체적이거나, 느슨한 것이다 라는 의미가, 구체적으로 어떤 것이 구체적인것인지 느슨한것인지 개념 갖기가 어려워서요, 그래서 위의 코드들도 명확하게 이해가 안됩니다.
제가 프로그래머 답지 않게 애매모호한 단어를 사용한 것 같네요. '느슨하다', '엄밀하다'는 제 머리 속에서만 추상적인 개념인 것 같아서 그 단어들은 잊어주세요!
집합 얘기를 하셨으니까 집합 얘기로 예를 들어보면
type Dog = "dog"
const dog = 1 as Dog // Error!
const dog2 = "hello" as Dog // Ok!
const dog = "hello" as Dog
에서 에러가 발생하지 않는 이유는 "hello" 라는 string literal type이 Dog
타입과 교집합이 되진 않지만 string
이라는 타입 아래 부모 집합 아래에 존재하기 때문입니다.
반면에 const dog = 1 as Dog
는 에러가 발생하는데 그 이유는 1 이라는 숫자가 Dog
라는 타입과 전혀 접점이 존재하지 않기 때문인데요.
그러니까 다시 질문의 원점으로 돌아와서 타입을 강제로 변환한다는 반은 맞고 반은 틀립니다. 이렇게 강제로 변환할 수 없는 케이스도 존재하기 때문입니다.
좀 더 실용적인 관점에서 as
의 사용방법을 말씀드리면, 타입스크립트가 완벽하지 않아서 어떤 경우엔 타입을 프로그래머가 as
를 사용해야 하는 경우도 존재합니다. 예를 들면,
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
getElementById
의 리턴 타입이 HTMLElement 이라서 타입스크립트가 그것밖에 추론을 못하지만, 프로그래머는 이미 main_canvas 가 HTMLCanvasElement 라는 것을 알고 있습니다. 그래서 이런 경우엔 사용해도 되겠죠?
따라서 되도록 타입스크립트가 추론할 수 있는 경우엔 as를 사용하는 것은 지양하고 아닌 경우엔 사용해야 하겠습니다.
안녕하세요!
매일매일 어떤 댓글을 남겨주실까 기대하며 찾아오는 즐거움?이 생겼네요!
답변 감사드립니다!
이후 강좌에서
말씀주신대로 'as', 'satisfies' 기대하겠습니다!
강의시청하며 궁금한 내용 있으면 질문남기겠습니다!
진심 감사드립니다!!
안녕하세요,
이런 사소한 질문(예: as의 의미)에 대해서 관심 가져주시고,
자세하게 설명해주셔서
정말 타입스크립트를 적극적으로 공부 할 동기부여가 됩니다!
덕분에 든든한?마음 갖고 타입스크립트 차근차근 배울 수 있게 해주셔서 감사합니다!
그럼 위 (제가 질문한)수식에서처럼,
사용되는
as를,
1. 어떤 대상을 암시적?으로 가리키면서(여기에서 T타입의 key를 의미),
뒤에 조건식의 내용을 '이어'가게 해주는 '의미적 사다리?" 라고
애매하게?나마 이해해도 될까요?
2.답변에 적어주신대로, "~로 사용하겠다" 라는 뉘앙스로 이해해도 될까요?
답변 남겨주신 내용에서 as의 내용이 아래와 같이 구분이 되서요!
=>
as
는[
as
뒤의 결과(타입 스페이스의 조건문, 즉${string}${'id'|'Id'}
의 패턴을 따르면 ]K를
[새로운 object의 키로 사용하고 아니라면 그 키를 버린다)를 Object의 Key]
로 사용하겠다
[라는 의미입니다.]
답변 남겨주서 as에 대해서 감?을 잡았는데, 이전 강의에서도 적용해보려고 합니다!
그리고 답변 남겨주시면서 예로 들어준, as의 타입을 변환하게 해주는 as 용도에 대해서 설명해주시면서,코멘트 부분이 이해가 안되서요
"타입의 조건은 as 앞에 있는 타입보다 좀 더 구체적이거나 느슨한 것으로 변경할 수 있다"
=>
좀 더 구체적이거나, 느슨한 것이다 라는 의미가, 구체적으로 어떤 것이 구체적인것인지 느슨한것인지 개념 갖기가 어려워서요, 그래서 위의 코드들도 명확하게 이해가 안됩니다.
제가 이해하고 있는 개념 중, 구체적이다, 느슨하다 라는 맥락은(언어의 느낌은),타입이 집합이란 범위 관점(타입할당 가능성)에서 인데요,
집합(타입)의 요소의 갯수가 많으면, 즉 갯수가 많으면 타입이 만족해야하는 조건들이 너무 구체적이라는 것과 그래서 만족할 타입들이 적어서, 타입의 범위가 작고, 요소의 갯수가 적으면, 많은 것에 비해, 요구조건이 상대적으로 쉬워서? 집합의 범위가 크다 , 이렇게 이해하고 있는데요,
혹시 이런 의미에서 구체적이다, 느슨하다 라고 하신건지요??
as의미를 강의해주신다니, 기대가 됩니다!
대부분 as를 as뒤 타입으로 변경한다 라고 단편적으로만 알려주는데,
구체적 의미까지 알려주신다니 궁금하네요!