![](/img/trans.png)
[英]TypeScript - infer function's argument type based on return type from another function
[英]Infer a type key from another object's values
我有一个界面专栏。
interface column {
field: string
label: string
}
所以一行列将是:
const cols = [{
label: 'First Name',
field: 'fname',
},
{
label: 'Last Name',
field: 'lname',
},
{
label: 'Email',
field: 'email',
}]
数据将是一组数据行。
const data:{}[] = [{
fname: 'bob', lname: 'dylan', email: 'db@email.com',
fname: 'van', lname: 'halen', email: 'vh@email.com'
}]
有没有办法强制数据的键,即 [fname, lname, email] 是相应 cols[n]['field'] 的值? 提前致谢。
是的,只要您以这样的方式定义cols
以使编译器不会将field
属性扩大到string
,您就可以这样做。 使用 TS3.4+ 最简单的方法是使用const
断言:
const cols = [{
label: 'First Name',
field: 'fname',
},
{
label: 'Last Name',
field: 'lname',
},
{
label: 'Email',
field: 'email',
}] as const;
这as const
意味着cols
将被视为只读元组,其中label
和field
属性具有字符串文字类型。
从那里您可以创建一个类型别名,将一组与Column
兼容的值转换为 object 类型,并将field
属性作为键。 当然没有提到每个字段的值类型应该是什么,所以我假设它总是string
:
interface Column {
field: string
label: string
};
type StringObjFromColumns<T extends readonly Column[]> =
{ [K in T[number]["field"]]: string }
然后我们可以将您的数据类型定义为StringObjFromColumns<typeof cols>
:
const data: StringObjFromColumns<typeof cols>[] = [{
fname: 'bob', lname: 'dylan', email: 'db@email.com',
}, {
fname: 'van', lname: 'halen', email: 'vh@email.com'
}, {
fname: 'van', lname: 'morrison', age: 75, email: 'vm@example.com' // error! age is extra
}, {
fname: 'ted', lname: 'nugent' // error! email is missing
}]
您可以看到它如何强制每个 object 必须具有这三个类型为string
的字段的约束。
好的,希望有帮助; 祝你好运!
这是不可能的,因为 typescript 类型是在编译时而不是运行时强制执行的。 请参阅我对这个问题的回答,它回答了你的问题。
这是一个棘手的问题。
有
interface Column {
field: string
label: string
}
我们可以定义一个RowObject
,另外,为了举例,一个Row
具有column
属性和row
本身。
interface RowObject {
[key: string]: string;
}
interface Row {
cols: Column[];
object: RowObject;
}
现在,我们应该定义一个 function 来制作新对象的原型。
const createRowBlueprint = (cols: Column[]): Row => {
return {
cols: [...cols],
object: cols.map(c => c.field)
.reduce((prop: RowObject, prev: string) => (prop[prev] = '', prop), {})
};
};
我刚刚定义了Row
接口来动态访问“真正的行对象”属性,就像这样
const row = createRowBlueprint(cols);
row.cols.forEach(col => {
const { field } = col;
const value = row.object[field];
console.log(`Field ${field} binded to ${value}`);
});
给定您的columns
集合,这将输出以下内容
{
cols: [
{ label: 'First Name', field: 'fname' },
{ label: 'Last Name', field: 'lname' },
{ label: 'Email', field: 'email' }
],
row: { fname: '', lname: '', email: '' }
}
Field fname binded to
Field lname binded to
Field email binded to
显然,我将默认值设置为空字符串。 但是,它有效的证明是从该字段访问的值不是undefined
。
最后,这种方法不是安全类型的。 但是,据我所知,Typescript 暂时不支持编译时的动态类型定义......所以这是一个棘手的解决方法。
希望能帮助到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.