string은 원시타입이고, String은 Reference type이다. 즉 String type은 객체형태로서 원시타입 string이 접근 할 수있는 프로퍼티와 메소드들을 가지고 있다.
보통 개발을 할때 문자열이라면 string type으로, 숫자형이라면 number type으로 지정하는게 일반적이다.
결론은 래퍼타입은 타입으로 사용해서는 안된다. => 일반적으로 원시타입이 효율적으로 메모리에 저장되기 때문
이러한 형태가 가능한이유는, JS는 원시값 (string, boolean, number) type에 대해 값을 참조하려고 한다면 일시적으로 Wrapper 객체로 변환한다.
그래서 String으로 선언하지 않았어도 String 객체의 프로퍼티나 매서드들을 사용 할 수 있는 것.
string & {} 은 문자 type 그대로 해석하면 string type과 {}type의 intersection이다.
빈 객체 type은 보통 null이 아니거나 undefined가 아닌 모든 type을 의미하기 때문에, 위 타입은
개념적으로는 string type과 같다.
하지만 차이점이라면, 일반적인 원시타입이 아니라 개발자가 의도적으로 명시한 type이라는 것이다. 즉, stirng & {} type은 string type처럼 Wrapper객체로 전환 될 수 없다.
const myString: string = 'Hello';
const myStringAndEmptyObject: string & {} = 'Hello';
console.log(myString.length); // ok
console.log(myStringAndEmptyObject.length); // error
첫번째 경우 => getColorString는 key들의 리터럴타입과 string을 파라미터로 받는다. => 여기서 string literal Type과 string타입의 union이기 때문에 string type으로 간주된다.
즉 어떠한 string도 올 수 있으며, TS 컴파일러는 string literal type을 자동완성 해주지 못한다. (애초에 literal type이 되지 않음.)
const knownColors = {
green: "#66bb6a",
red: "#ef9a9a",
blue: "#81d4fa",
} as const;
function getColorString(color: keyof typeof knownColors | string): string {
if (color in knownColors)
return knownColors[color as keyof typeof knownColors];
return color;
}
두번째 경우
이 경우는 string literal type의 union으로, TS 컴파일러가 미리 어떤 type이 올지 미리 말해준다.
function getColor(color: (keyof typeof knownColors) | (string & {})): string {
if (color in knownColors)
return knownColors[color as keyof typeof knownColors];
return color;
}
세번째 경우
두번째 경우와 동일한데, 이를 오버로딩으로도 구현 할 수 있다.
function getColorOvld(color: (keyof typeof knownColors)): string;
function getColorOvld(color: string): string;
function getColorOvld(color: string): string {
if (color in knownColors)
return knownColors[color as keyof typeof knownColors];
return color;
}
ref) https://stackoverflow.com/questions/61047551/typescript-union-of-string-and-string-literals
https://github.com/microsoft/TypeScript/issues/29729