带有可选功能的类型操作

问题描述 投票:0回答:1

需要类型操作方面的帮助。我有这个界面

interface IFormData<Inputs> {
    data: Inputs;
    transformData?: (data: Inputs) => <Result of data transformation>;
    getData?: (values: Inputs or "Result of data transformation") => {...}
}

请注意,

transformData
可以作为函数传递,也可以不传递,这是一个可选参数。

如何实现,以便在传递

transformData
函数时,我们改变
getData(values: ...)
中的类型?

界面功能

function transformer<T>({
    getData,
    transformData,
    data
}: IFormData<T>) {
    if(getData) {
        if(transformData) {
            getData(transformData(data)) // something to do
        } else {
            getData(data) // something to do
        }
    }
}

示例:

  1. transformData

    transformer({
        data: {
            first_name: "",
            last_name: "string",
            age: 34
        },
        transformData: (data) => {
            return {
                fullname: data.first_name + " " + data.last_name,
                age: data.age
            }
        },
        getData(values) {
            "values" must be {
                fullname: string; 
                age: number
            }
        }
    })
    
  2. 没有

    transformData

    transformer({
        data: {
            first_name: "John",
            last_name: "Makeev",
            age: 34
        },
        getData(values) {
            "values" must be {
                first_name: string;
                last_name: string 
                age: number
            }
        }
    })
    

Result 是一个接口,可以帮助我执行正确的函数类型

示例链接

typescript
1个回答
0
投票

为了使其正常工作,您的

IFormData
类型需要在 I 输入的
data
类型和
R
返回类型的 transformData 类型中均为
generic
:
interface IFormData<I, R> {
    data: I;
    transformData?: (data: I) => R,
    getData?: (values: R) => any; 
}

那么你的 
transformer

函数必须同样通用。您可以为

R
提供
I
默认类型参数,以便当 TypeScript 无法从函数输入推断
R
时,它会回退到
I
。 这样,省略
transformData
的调用将获得此默认值,然后
getData
将根据需要将
I
作为输入类型:
function transformer<I, R = I>({
    getData,
    transformData,
    data
}: IFormData<I, R>): void;

让我们测试一下。首先,当我们经过
transformData

时:

transformer({
    data: {
        first_name: "",
        last_name: "string",
        age: 34
    },
    transformData: (data) => {
        return {
            fullname: data.first_name + " " + data.last_name,
            age: data.age
        }
    },
    getData(values) {
        /* (parameter) values: {
            fullname: string;
            age: number;
        } */

    }
})

看起来不错。这里 
data

transformData
参数被
上下文类型化
为来自 I 属性类型的
{first_name: string, last_name: string, age: number}
类型
data
。并且
values
getData
参数根据上下文类型为
R
返回类型的
{fullname: string, age: number}
类型
transformData
然后,不带

transformData

打电话:

transformer({
    data: {
        first_name: "John",
        last_name: "Makeev",
        age: 34
    },
    getData(values) {
        /* (parameter) values: {
            first_name: string;
            last_name: string;
            age: number;
        } */
    }
})

这个看起来也不错。 
values

getData
参数的类型已根据上下文从
{first_name: string, last_name: string, age: number}
的默认类型参数中输入为
R
,这与
I
相同,后者是从
 的类型推断出来的data
财产。

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.