请教在Typescript中如何使用递归函数返回正确的数据类型?

TS演示:https://tsplay.dev/mLO04N , 问题:当我将reduce中返回对象的children注释去掉,返回的类型就变成any了,请问正确姿势应该是?

interface LocationItem {
    code: string;
    name: string;
    cities?: Record<string, LocationItem>;
    districts?: Record<string, string>;
}

interface Option {
    value: string | number;
    label: string;
    children?: Option[];
}

const objectEntries = <T extends object, K = keyof T>(obj: T) => Object.entries(obj) as Array<[K, T[keyof T]]>;

const transform = (data: Record<string, LocationItem | string>|undefined = {}) =>
    objectEntries(data).reduce((buf, [key, value]) => {
        if (typeof value === "string") {
            return [...buf, { label: value, value: key }];
        }

        const { code, name, cities, districts } = value;
        const _cities = transform(cities);
        const _districts = transform(districts);

        const children = _cities.length ? _cities : _districts.length ? _districts : undefined;
        return [
            ...buf,
            {
                label: name,
                value: code,
                // children,
            },
        ];
    }, [] as Option[]);

我把提取的值像这样复制给一个对象,获取的类型是对的,但是如果把这个对象作为返回数据类型就不对了

3241709885134_.pic.jpg

请不要试图类似用下面断言的方式来解决,我试图通过正确的姿势获取数据类型:

const _cities = transform(cities) as Options[];
const _districts = transform(districts) as Options[];
阅读 2.3k
2 个回答
✓ 已被采纳
const transform = (data: Record<string, LocationItem | string> = {}) =>
    Object.entries(data).reduce<Option[]>((buf, [key, value]) => {
        if (typeof value === 'string') buf.push({ label: value, value: key })
        else {
            const { code, name, cities, districts } = value
            const _cities = transform(cities)
            const _districts = transform(districts)

            const children = _cities.length
                ? _cities
                : _districts.length
                ? _districts
                : undefined
            buf.push({ label: name, value: code, children: children })
        }
        return buf
    }, [])

可以考虑把return的数据项单独声明并赋予类型:

// ...省略
const item: Option = {
  label: name,
  value: code,
  children: _cities.length
    ? _cities
    : _districts.length
    ? _districts
    : undefined,
};
return [...buf, item];

完整示例

本质原因是因为 Option[] | undefined 导致的类型匹配错误,或者在各个中间变量的定义中都加上正确的类型声明也能解决

logo
Microsoft
子站问答
访问
宣传栏