将 class 名称注入样式化组件时的输入
Typings when injecting class name into styled components
请帮我修正打字问题。
我想将 class 名称注入样式组件。
我做了这个功能:
type IntrinsicElementsKeys = keyof { div: any, a: any } /* could be keyof JSX.IntrinsicElements */
export function elementWithClass(e: IntrinsicElementsKeys, customClassName: string) {
/* [2] if I don't force the type ts does not allow me to call se.attrs() */
const se = styled[e] as ThemedStyledFunction<typeof e, any>
const res = se.attrs(props => ({
className: customClassName + " " + (props.className || "")
}))``
/* [1] if I don't force "any" then I cannot use native props such as "href" */
return res as any;
}
我想去掉 [1] 处的“任何”,但如果我这样做并按如下方式调用组件:
const Link = elementWithClass("a", "rick-roll")
const MyElement: React.FC<{ /* props */ }> = props => <Link href="http://rick-roll.com">rick</Link>
然后 TS 抱怨“href”是一个未知的 props。
所以我的问题是:如何修复我的打字?
注意 1: 如果我删除 [2] 处的“as”,那么 TS 会抱怨
Each member of the union type '(<U, NewA extends Partial<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof HTMLAttributes<...>> & { ...; } & U> & { ...; } = {}>(attrs: Attrs<...>) => ThemedStyledFunction<...>) | (<U, NewA extends Partial<...> & { ...; } = {}>(attrs: Attrs<...>) => ThemedStyledFunction<...>)' has signatures, but none of those signatures are compatible with each other.
注2:此题与
但更具体地说明了如何使用我使用的特定方法修复输入。
所以您首先应该想到的是,如果您希望 return 类型根据输入而不同,您很可能应该 包括泛型 .
所以,让我们来解决这个问题!
type IntrinsicElementsKeys = "div" | "a"; /* could be keyof JSX.IntrinsicElements */
// 1st step, let's introduce the generic inside the function
export function elementWithClass<T extends IntrinsicElementsKeys>(e: T, customClassName: string) {
// 2nd step, let's pass it in ThemedStyledFunction
const se = styled[e] as ThemedStyledFunction<T, any>;
// 3rd step, pass in the generic into the `attrs` function
const res = se.attrs<T>(props => ({
className: customClassName + " " + (props.className || "")
}))``
/* [1] if I don't force "any" then I cannot use native props such as "href" */
return res;
}
const Link = elementWithClass("a", "rick-roll")
const MyElement: React.FC<{ /* props */ }> = props => <Link href="http://rick-roll.com">rick</Link> // all good
const Link1 = elementWithClass("div", "rick-roll")
const MyElement1: React.FC<{ /* props */ }> = props => <Link1 href="http://rick-roll.com">rick</Link1> // error
只需按照以下步骤,即可推断出道具类型!
- 引入一个泛型来接受元素;
- 将泛型添加到
ThemedStyledFunction
;
- 将泛型添加到
attrs
函数;
这里有一个playground link,你也可以用它来玩。
请帮我修正打字问题。
我想将 class 名称注入样式组件。 我做了这个功能:
type IntrinsicElementsKeys = keyof { div: any, a: any } /* could be keyof JSX.IntrinsicElements */
export function elementWithClass(e: IntrinsicElementsKeys, customClassName: string) {
/* [2] if I don't force the type ts does not allow me to call se.attrs() */
const se = styled[e] as ThemedStyledFunction<typeof e, any>
const res = se.attrs(props => ({
className: customClassName + " " + (props.className || "")
}))``
/* [1] if I don't force "any" then I cannot use native props such as "href" */
return res as any;
}
我想去掉 [1] 处的“任何”,但如果我这样做并按如下方式调用组件:
const Link = elementWithClass("a", "rick-roll")
const MyElement: React.FC<{ /* props */ }> = props => <Link href="http://rick-roll.com">rick</Link>
然后 TS 抱怨“href”是一个未知的 props。
所以我的问题是:如何修复我的打字?
注意 1: 如果我删除 [2] 处的“as”,那么 TS 会抱怨
Each member of the union type '(<U, NewA extends Partial<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof HTMLAttributes<...>> & { ...; } & U> & { ...; } = {}>(attrs: Attrs<...>) => ThemedStyledFunction<...>) | (<U, NewA extends Partial<...> & { ...; } = {}>(attrs: Attrs<...>) => ThemedStyledFunction<...>)' has signatures, but none of those signatures are compatible with each other.
注2:此题与
所以您首先应该想到的是,如果您希望 return 类型根据输入而不同,您很可能应该 包括泛型 .
所以,让我们来解决这个问题!
type IntrinsicElementsKeys = "div" | "a"; /* could be keyof JSX.IntrinsicElements */
// 1st step, let's introduce the generic inside the function
export function elementWithClass<T extends IntrinsicElementsKeys>(e: T, customClassName: string) {
// 2nd step, let's pass it in ThemedStyledFunction
const se = styled[e] as ThemedStyledFunction<T, any>;
// 3rd step, pass in the generic into the `attrs` function
const res = se.attrs<T>(props => ({
className: customClassName + " " + (props.className || "")
}))``
/* [1] if I don't force "any" then I cannot use native props such as "href" */
return res;
}
const Link = elementWithClass("a", "rick-roll")
const MyElement: React.FC<{ /* props */ }> = props => <Link href="http://rick-roll.com">rick</Link> // all good
const Link1 = elementWithClass("div", "rick-roll")
const MyElement1: React.FC<{ /* props */ }> = props => <Link1 href="http://rick-roll.com">rick</Link1> // error
只需按照以下步骤,即可推断出道具类型!
- 引入一个泛型来接受元素;
- 将泛型添加到
ThemedStyledFunction
; - 将泛型添加到
attrs
函数;
这里有一个playground link,你也可以用它来玩。