在流程中,我可以这样定义一个动态文字类型:
const myVar = 'foo'
type X = {
[typeof myVar]: string
}
const myX: X = { foo: 1 } // will throw, because number
const myX: X = { foo: 'bar' } // will not throw
我正在尝试将一些代码转换为打字稿,而这种语法是不可能的。但是,我不知道如何在打字稿中做到这一点。这是我正在使用的代码(已经部分翻译成打字稿):
type Theme = {
fontSizes: number[]
}
type SystemObj = {
prop: string,
cssProperty?: string,
}
type Props<T> = T & {
theme: Theme,
}
const style = <X>({
prop,
cssProperty,
}: SystemObj) => {
const cssProp = cssProperty || prop
return (props: Props<{
[typeof cssProp]: X
}>) => {
return props
}
}
const fontSize = style<number>({
prop: 'fontSize',
})
fontSize({
fontSize: 2,
theme: {
fontSizes: [12, 14, 16],
}
})
当前抛出(在打字稿游乐场上所有选项均已打开)
Argument of type '{ fontSize: number; theme: { fontSizes: number[]; }; }' is not assignable to parameter of type '{ theme: Theme; }'.
Object literal may only specify known properties, and 'fontSize' does not exist in type '{ theme: Theme; }'.
编辑:
所以我得到了它的工作,正是我希望它如何工作:
type Theme = {
fontSizes: number[]
}
type SystemObj = {
prop: string,
cssProperty?: string,
}
type Props = {
theme: Theme,
}
const style = <X extends string, Y>({
prop,
cssProperty,
}: SystemObj) => {
const cssProp = cssProperty || prop
return (props: Props & { [K in X]: Y }) => {
return props
}
}
const fontSize = style<'fontSize', number>({
prop: 'fontSize',
})
fontSize({
fontSize: 123,
theme: {
fontSizes: [12, 14, 16],
}
})
是否可以在这里摆脱<'fontSize'
部分?
const fontSize = style<'fontSize', number>({
prop: 'fontSize',
})
,然后输入为
const fontSize = style<number>({
prop: 'fontSize',
})
它完全按照我想要的方式工作,只是想知道我是否可以在这里删除重复项(因为prop: 'fontSize'
已经定义了密钥)。这就引出了我最初的问题,即如何在此处定义值fontSize
作为类型内的键。
答案 0 :(得分:0)
当前这是不可能的,因为您要部分指定和部分推断类型参数。一旦this PR进入TypeScript,您将可以执行以下操作:
type SystemObj<T extends string> = { // <------ note T here
prop: T,
cssProperty?: string,
}
type Props = {
theme: Theme,
}
const style = <X extends string, Y>({
prop,
cssProperty,
}: SystemObj<X>) => { // <---------------------- X as an argument here
const cssProp = cssProperty || prop
return (props: Props & { [K in X]: Y }) => {
return props
}
}
const fontSize = style<_, number>({ // <-------- Ask TS to infer type param
prop: 'fontSize',
})
fontSize({
fontSize: 123,
theme: {
fontSizes: [12, 14, 16],
}
})
答案 1 :(得分:0)
如果没有部分参数类型推断,则可以将style
函数拆分为“两部分”-style
将返回接受SystemObj
的函数。这样,您就可以指定值类型(number
),并且可以从SystemObj
推断道具名称:
type SystemObj<TProp extends string> = {
prop: TProp,
cssProperty?: string,
}
const style = <TValue>() =>
<TKey extends string>(systemObj: SystemObj<TKey>) =>
(props: Props & { [K in TKey]: TValue }) => props
const fontSize = style<number>()({
prop: 'fontSize',
})
fontSize({
fontSize: 123,
theme: {
fontSizes: [12, 14, 16],
}
})