#typescript #enums
#typescript #перечисления
Вопрос:
Я добавляю текстовый компонент в Typescript, который может иметь несколько разных типов: <Text type='h2'>Hello World</Text>
.
Я использую объект styles, который имеет эти типы в качестве ключей, чтобы я мог извлекать из них правильные стили. Этот тип должен быть только одной из нескольких возможностей.
import React from 'react'
import { colors } from '../../config'
const getKeyValue = <U extends keyof T, T extends object>(key: U) => (obj: T) => obj[key]
const styles = {
h1: {
fontSize: "46px",
lineHeight: "64px",
fontWeight: 300,
},
h2: {
fontSize: "34px",
lineHeight: "48px",
fontWeight: 300,
},
h3: {
fontSize: "28px",
lineHeight: "40px",
fontWeight: 400,
},
h4: {
fontSize: "23px",
lineHeight: "32px",
fontWeight: 400,
},
h5: {
fontSize: "16px",
lineHeight: "32px",
fontWeight: 600,
},
h6: {
fontSize: "13px",
lineHeight: "24px",
fontWeight: 600,
},
h7: {
fontSize: "11px",
lineHeight: "16px",
fontWeight: 600,
},
subtitle1: {
fontSize: "16px",
lineHeight: "24px",
fontWeight: 600,
},
subtitle2: {
fontSize: "12px",
lineHeight: "16px",
fontWeight: 600,
},
body1: {
fontSize: "16px",
lineHeight: "24px",
fontWeight: 400,
},
body2: {
fontSize: "13px",
lineHeight: "24px",
fontWeight: 400,
},
button: {
fontSize: "13px",
lineHeight: "24px",
fontWeight: 600,
},
caption: {
fontSize: "11px",
lineHeight: "16px",
fontWeight: 400,
}
}
interface Style {
fontSize: string;
lineHeight: string;
fontWeight: number;
}
interface Styles {
h1: Style; h2: Style; h3: Style; h4: Style; h5: Style; h6: Style; h7: Style;
subtitle1: Style; subtitle2: Style; body1: Style; body2: Style; button: Style; caption: Style;
}
interface Props {
children: string;
type: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'h7' | 'subtitle1' | 'subtitle2' | 'body1' | 'body2' | 'button' | 'caption';
color?: string;
ellipsis?: boolean;
fontWeight?: any;
onChange?: any;
}
const Text = ({ children, type, color = colors.darkGrey, ellipsis = false, fontWeight }: Props) => {
const style = {
...getKeyValue<keyof Styles, Styles>(type)(styles),
color,
minHeight: 25, // TODO: remove this arbitrary height
textOverflow: ellipsis ? 'ellipsis' : 'none',
overflow: ellipsis ? 'hidden' : 'none',
whiteSpace: ellipsis ? 'nowrap' : 'none',
} as React.CSSProperties
if (typeof fontWeight !== 'undefined') {
style.fontWeight = fontWeight
}
return <div style={style} >{children}</div>
}
export default Text
Это все хорошо, но я объявляю ключи объекта styles три раза:
- В самом объекте styles
- В интерфейсе стилей
- В объявлении типа
type
Это кажется излишним, но я слишком новичок в Typescript, чтобы знать, как я могу сделать лучше.
Можно ли это сделать более кратким / лучшим способом, и если да, то как?
Ответ №1:
Вы можете определить Styles
и type
в отношении предполагаемого типа styles
константы. Чтобы получить тип константы, которую мы можем использовать typeof
, и получить ключи того типа, который мы можем использовать keyof
. Затем мы можем использовать Record
для создания Styles
типа (запись — это тип с заданным набором ключей одного и того же типа)
type StyleType = keyof typeof styles
type Styles = Record<StyleType, Style>