Typescript接口属性为string
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Typescript接口属性为string相关的知识,希望对你有一定的参考价值。
目的
我有一个接口TypeScript:
interface IInterface
id: number;
name: string;
我有一些方法可以输入属性的名称(字符串)。
例如:
var methodX = ( property: string, object: any ) =>
// use object[property]
;
我的问题是,当我调用methodX
时,我必须在字符串中写入属性名称。
例如:对象实现接口的methodX("name", objectX);
但这很糟糕:如果我重命名一个属性(假设我想将name
重命名为lastname
),我将不得不手动更新我的所有代码。
我不希望这种依赖。
由于typescript接口没有JS实现,我不知道我怎么不能使用字符串。
我希望有类似的东西:methodX(IInterface.name.propertytoString(), objectX);
我是JS的新手,你看到另一种选择吗?
(可选)更多细节:为什么我需要将属性作为参数传递,为什么我不使用泛型方法?
我使用链接数据的方法:
linkData = <TA, TB>(
inputList: TA[],
inputId: string,
inputPlace: string,
outputList: TB[],
outputId: string ) =>
var mapDestinationItemId: any = ;
var i: number;
for ( i = 0; i < outputList.length; ++i )
mapDestinationItemId[outputList[i][outputId]] = outputList[i];
var itemDestination, itemSource;
for ( i = 0; i < inputList.length; ++i )
itemDestination = inputList[i];
itemSource = mapDestinationItemId[itemDestination[inputId]];
if ( itemSource )
itemDestination[inputPlace] = itemSource;
;
但TA和TB可以有很多不同的ID。所以我不知道如何使它更通用。
basarat答案是一个好主意,但它不适用于接口。
你不能写methodX(interfacePropertyToString(()=>interfaceX.porpertyname), objectX)
因为interfaceX
不是一个对象。
接口是抽象,它们仅用于TypeScript,它们在javascript中不存在。
但是由于他的回答,我找到了解决方案:在方法中使用参数。
最后我们有:
interfacePropertyToString = ( property: (object: any) => void ) =>
var chaine = property.toString();
var arr = chaine.match( /[\s\S]*[\s\S]*\.([^\.; ]*)[ ;\n]*/ );
return arr[1];
;
我们必须使用[\s\S]
才能在多线上匹配,因为Typescript将(object: Interface) => object.code;
转换为多线函数。
现在您可以根据需要使用它:
interfacePropertyToString(( o: Interface ) => o.interfaceProperty);
interfacePropertyToString( function ( o: Interface ) o.interfaceProperty);
您可以编写一个函数来解析函数体,以查找名称,例如:
methodX(getName(()=>something.name), objectX)
其中getName
将在函数体上执行toString
以获取"function()return something.name"
形式的字符串,然后解析它以获得"name"
。
注意:然而,根据您如何缩小它,这种趋势会有所突破。
一些相关的问题 - 如何获取/设置属性路径的值。我写了两个课:
export class PropertyPath
static paths = new Map<string, PropertyPath>()
static get<T, P>(lambda: (prop:T) => P) : PropertyPath
const funcBody = lambda.toString();
var ret : PropertyPath = this.paths[funcBody];
if (!ret)
const matches = funcBody.match( /(?:return[\s]+)(?:\w+\.)((?:\.?\w+)+)/ ); //first prop ignores
var path = matches[1];
ret = new PropertyPath(path.split("."));
this.paths[funcBody] = ret;
return ret;
;
path : Array<string>
constructor(path : Array<string>)
this.path = path
getValue( context : any)
const me = this;
var v : any;
return this.path.reduce( (previous, current, i, path) =>
try
return previous[current];
catch (e)
throw
message : `Error getting value by path. Path: '$path.join(".")'. Token: '$current'($i)`,
innerException: e
;
, context)
setValue( context : any, value : any)
const me = this;
var v : any;
this.path.reduce( (previous, current, i, path) =>
try
if (i == path.length - 1)
previous[current] = value
return previous[current];
catch (e)
throw
message : `Error setting value by path. Path: '$path.join(".")'. Token: '$current'($i). Value: $value`,
innerException: e
;
, context)
用法示例:
var p = PropertyPath.get((data:Data) => data.person.middleName)
var v = p.getValue(data)
p.setValue(data, newValue)
一些糖:
export class PropertyPathContexted
static get<T, P>(obj : T, lambda: (prop:T) => P) : PropertyPathContexted
return new PropertyPathContexted(obj, PropertyPath.get(lambda));
;
context: any
propertyPath: PropertyPath
constructor(context: any, propertyPath: PropertyPath)
this.context = context
this.propertyPath = propertyPath
getValue = () => this.propertyPath.getValue(this.context)
setValue = ( value : any) => this.propertyPath.setValue(this.context, value)
用法:
var p = PropertyPathContexted.get(data, () => data.person.middleName)
var v = p.getValue()
p.setValue("lala")
我在React中找到了最新的双向数据绑定方便:
var valueLink = function<T, P>( context: T, lambda: (prop:T) => P)
var p = PropertyPathContexted.get(context, lambda);
return
value: p.getValue(),
requestChange: (newValue) =>
p.setValue(newValue);
;
render()
var data = getSomeData()
//...
return (
//...
<input name='person.surnames' placeholder='Surnames' valueLink=valueLink(data, () => data.person.surnames)/>
//...
)
我稍微更改了basarat代码,因此我们可以将它用作通用代码:
const P = <T>( property: (object: T) => void ) =>
const chaine = property.toString();
const arr = chaine.match( /[\s\S]*[\s\S]*\.([^\.; ]*)[ ;\n]*/ );
return arr[1];
;
示例用法:
console.log(P<MyInterface>(p => p.propertyName));
以上是关于Typescript接口属性为string的主要内容,如果未能解决你的问题,请参考以下文章