Templee_0309) TypeScript + string Key to Object

오범준·2021년 3월 7일
0

Error Message

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'WidthSize'.
No index signature with a parameter of type 'string' was found on type 'WidthSize'.

// Width ( 24px default 는 제외 )
// 12, 14, 16, 18, 32 px
type WidthType = 'xxsmall' | 'xsmall' | 'small' | 'middle' | 'large';
type WidthSize = {
  [K in WidthType]: string;
};
const Width: WidthSize = {
  xxsmall: '12px',
  xsmall: '14px',
  small: '16px',
  middle: '18px',
  large: '32px',
};

// Height ( 24px default 는 제외 )
type HeightType = 'xxsmall' | 'xsmall' | 'small' | 'middle' | 'large';
type HeightSize = {
  [K in HeightType]: string;
};
const Height: HeightSize = {
  xxsmall: '12px',
  xsmall: '14px',
  small: '16px',
  middle: '18px',
  large: '32px',
};

const IconBlockWrapper = styled.div<{
  src: string;
  width?: string;
  height?: string;
}>`
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: ${(props) => (props.width ? Width[props.width] : '24px')};
  height: ${(props) => (props.height ? props.height : '24px')};
  background: url(${(props) => props.src});
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
`;

SQ

I am trying to use
'xxsmall', 'xsmall' .....
as an 'Key' of 'Width' OBJ

But, since ( ex) 'xxsmall' ) type is 'string' ,
it is throwing Error

Why ? why 'string' cannot be used as an 'index' above ?

link : https://soopdop.github.io/2020/12/01/index-signatures-in-typescript/

Because it is 'Typescript'

To be more exact ,
The reason behind above error is ,
you are using 'string type' to place where 'string literal' is only allowed

String vs String Literal

const a = "Hello World"
let b   = "Hello World"
const c : string = "Hello World"

1) 'b' 💗 String Type
decleard with 'let', which means any additional 'string' can be allocated to variable 'b'
2) 'c' : 'const' + ': string' 💗 string type
only 'string' type can be allocated to 'c'

3) 'a' ?

Literal Narrowing

compiler infer 'c' as more 'narrow' string type

that is,
'a' is "not" 💗 String Type

'a' is 💗 String literal Type

that is, only 'Hello World' can be allocated !

Using 'String Literal' as 'key' to approach 'Obj'

const obj = {
  foo: "hello",
}

const propertyName = "foo"

console.log(obj[propertyName]) // ok!
console.log(obj["foo"]) // ok!

it works fine . WHY ?
'propertyName' & 'obj' is 'literal type'


However

for (const key of Object.keys(obj)) {
  console.log(obj[key]) // compile error! key가 string타입이다.
}

Error !
WHY?
Because, Object.keys() return 'string[]' !

which means that 'key' in 'obj[key]' is 'string' type, not 'literal' type

Sample Solution : index signature

type ObjType = {
  [index: string]: string
  foo: string
  bar: string
}

const obj: ObjType = {
  foo: "hello",
  bar: "world",
}

const propertyName1 = "foo"
const propertyName2: string = "foo"

console.log(obj[propertyName1]) // ok
console.log(obj[propertyName2]) // ok

Solution

< Before >
type WidthSize = {
  [K in WidthType ]: string;
};

< After >
type WidthSize = {
  [K in WidthType as string]: string;
};

it means we are typing 'K' as 'string',
not 'string literal'

allow using 'string type key' to approach 'obj'

profile
Dream of being "물빵개" ( Go abroad for Dance and Programming)

0개의 댓글