type: Checkbox.Group type infer (#46423)

* feat: CheckboxGroup type infer

fix: fix type error

fix: define type infer

chore: opti type

* Update type.test.tsx

Signed-off-by: lijianan <574980606@qq.com>

* Update Group.tsx

Signed-off-by: lijianan <574980606@qq.com>

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gushuo <gushuo@yoycol.com>
Co-authored-by: lijianan <574980606@qq.com>
This commit is contained in:
dally_G 2023-12-22 17:07:34 +08:00 committed by GitHub
parent 924f46fd88
commit 0647f56856
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 138 additions and 131 deletions

View File

@ -11,9 +11,9 @@ import useStyle from './style';
export type CheckboxValueType = string | number | boolean;
export interface CheckboxOptionType {
export interface CheckboxOptionType<T extends CheckboxValueType = CheckboxValueType> {
label: React.ReactNode;
value: CheckboxValueType;
value: T;
style?: React.CSSProperties;
disabled?: boolean;
title?: string;
@ -22,27 +22,29 @@ export interface CheckboxOptionType {
required?: boolean;
}
export interface AbstractCheckboxGroupProps {
export interface AbstractCheckboxGroupProps<T extends CheckboxValueType = CheckboxValueType> {
prefixCls?: string;
className?: string;
rootClassName?: string;
options?: Array<CheckboxOptionType | string | number>;
options?: (CheckboxOptionType<T> | string | number)[];
disabled?: boolean;
style?: React.CSSProperties;
}
export interface CheckboxGroupProps extends AbstractCheckboxGroupProps {
export interface CheckboxGroupProps<T extends CheckboxValueType = CheckboxValueType>
extends AbstractCheckboxGroupProps<T> {
name?: string;
defaultValue?: Array<CheckboxValueType>;
value?: Array<CheckboxValueType>;
onChange?: (checkedValue: Array<CheckboxValueType>) => void;
defaultValue?: T[];
value?: T[];
onChange?: (checkedValue: T[]) => void;
children?: React.ReactNode;
}
const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGroupProps> = (
props,
ref,
) => {
const CheckboxGroup = React.forwardRef(
<T extends CheckboxValueType = CheckboxValueType>(
props: CheckboxGroupProps<T>,
ref: React.ForwardedRef<HTMLDivElement>,
) => {
const {
defaultValue,
children,
@ -56,10 +58,8 @@ const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGrou
} = props;
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const [value, setValue] = React.useState<CheckboxValueType[]>(
restProps.value || defaultValue || [],
);
const [registeredValues, setRegisteredValues] = React.useState<CheckboxValueType[]>([]);
const [value, setValue] = React.useState<T[]>(restProps.value || defaultValue || []);
const [registeredValues, setRegisteredValues] = React.useState<T[]>([]);
React.useEffect(() => {
if ('value' in restProps) {
@ -67,9 +67,9 @@ const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGrou
}
}, [restProps.value]);
const memoOptions = React.useMemo(
const memoOptions = React.useMemo<CheckboxOptionType<T>[]>(
() =>
options.map<CheckboxOptionType>((option) => {
options.map<CheckboxOptionType<T>>((option: CheckboxOptionType<T>) => {
if (typeof option === 'string' || typeof option === 'number') {
return { label: option, value: option };
}
@ -78,15 +78,15 @@ const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGrou
[options],
);
const cancelValue = (val: string) => {
const cancelValue = (val: T) => {
setRegisteredValues((prevValues) => prevValues.filter((v) => v !== val));
};
const registerValue = (val: string) => {
const registerValue = (val: T) => {
setRegisteredValues((prevValues) => [...prevValues, val]);
};
const toggleOption = (option: CheckboxOptionType) => {
const toggleOption = (option: CheckboxOptionType<T>) => {
const optionIndex = value.indexOf(option.value);
const newValue = [...value];
if (optionIndex === -1) {
@ -162,11 +162,12 @@ const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGrou
<GroupContext.Provider value={context}>{childrenNode}</GroupContext.Provider>
</div>,
);
};
},
);
export type { CheckboxGroupContext } from './GroupContext';
export { GroupContext };
const CheckboxGroup = React.forwardRef<HTMLDivElement, CheckboxGroupProps>(InternalGroup);
export default React.memo(CheckboxGroup);
export default CheckboxGroup as <T extends CheckboxValueType = CheckboxValueType>(
props: CheckboxGroupProps<T> & React.RefAttributes<HTMLDivElement>,
) => React.ReactNode;

View File

@ -1,13 +1,13 @@
import React from 'react';
import type { CheckboxOptionType } from './Group';
import type { CheckboxOptionType, CheckboxValueType } from './Group';
export interface CheckboxGroupContext {
export interface CheckboxGroupContext<T extends CheckboxValueType = CheckboxValueType> {
name?: string;
toggleOption?: (option: CheckboxOptionType) => void;
value?: any;
disabled?: boolean;
registerValue: (val: string) => void;
cancelValue: (val: string) => void;
registerValue: (val: T) => void;
cancelValue: (val: T) => void;
}
const GroupContext = React.createContext<CheckboxGroupContext | null>(null);

View File

@ -13,11 +13,17 @@ describe('Checkbox.typescript', () => {
it('Checkbox.Group', () => {
const group = (
<Checkbox.Group>
<Checkbox.Group<'test-type-1' | 'test-type-2' | 'test-type-3'>
options={[
{
label: <span>test</span>,
value: 'test-type-1',
},
]}
>
<Input />
</Checkbox.Group>
);
expect(group).toBeTruthy();
});
});