Angular 类接口函数定义-类型错误:对象不';不支持属性或方法
我在Angular应用程序中编写了一个类似于以下内容的构造(为了演示这个问题,已经对其进行了极大的简化)。什么会阻止在Angular 类接口函数定义-类型错误:对象不';不支持属性或方法,angular,typescript,typescript2.0,Angular,Typescript,Typescript2.0,我在Angular应用程序中编写了一个类似于以下内容的构造(为了演示这个问题,已经对其进行了极大的简化)。什么会阻止在DemoSource类中的项实例上定义filterProperty()函数 export关键字被使用,因为每个构造都在一个单独的文件中定义。 export interface IProperty { filterProperty(): string; } export class Demo implements IProperty { displayName:
DemoSource
类中的项实例上定义filterProperty()
函数
export
关键字被使用,因为每个构造都在一个单独的文件中定义。
export interface IProperty {
filterProperty(): string;
}
export class Demo implements IProperty {
displayName: string;
filterProperty(): string {
return this.displayName;
}
}
export class DemoSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
constructor(private service: IService<TItem>) {
// A BehaviorSubject<Array<TItem>> from a service
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
return Observable.merge(this.service.data).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
// Object doesn't support property or method 'filterProperty'
const searchStr = item.filterProperty().toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
下面是使用API中的数据填充的服务:
以下是来自浏览器的纯API调用的结果:
某些属性因其数据而被修订
更新-传输的JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
更新
演示问题的Web应用程序:
Web应用程序的GitHub Repo:,因为我认为过滤器
是保留关键字。因此,尝试在类型对象
上实现过滤器
函数<代码>过滤器
只能用于阵列
。尝试为函数使用不同的名称
如果不是这样的话。也许服务数据项应该作为Object
而不是TTem
实例出现。我们只能在其实例上获得类方法。您可以尝试如下创建新实例吗
this.filteredData = this.service.data.value.slice().filter(
(item: TItem) => {
// Object doesn't support property or method 'filter'
let instance: TItem = new TItem();
Object.assign(instance, item);
const searchStr = instance.filter().toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !==-1;
});
我认为,filter
是保留关键字。因此,尝试在类型对象
上实现过滤器
函数<代码>过滤器
只能用于阵列
。尝试为函数使用不同的名称
如果不是这样的话。也许服务数据项应该作为Object
而不是TTem
实例出现。我们只能在其实例上获得类方法。您可以尝试如下创建新实例吗
this.filteredData = this.service.data.value.slice().filter(
(item: TItem) => {
// Object doesn't support property or method 'filter'
let instance: TItem = new TItem();
Object.assign(instance, item);
const searchStr = instance.filter().toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !==-1;
});
我能够让它工作的方式,我原本希望它与下面的设置。很显然,关键在于向C#对象添加一个
filter
属性,该对象用于通过Web API将数据序列化为JSON。不确定为什么需要这样做,因为TypeScript应该能够使用附加功能扩展从Web API接收的模型
简化示例以演示问题集
DemoModel.cs
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
iproperty.interface.ts
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
demo.model.ts
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
core.datasource.ts
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
导出类CoreDataSource{
filterChange=新行为主体(“”);
过滤数据:滴度[];
get filter():字符串{返回this.filterChange.value;}
设置过滤器(过滤器:字符串){this.filterChange.next(过滤器);}
建造商(私人服务:iSeries){
超级();
this.filteredData=service.data.value.slice();
}
connect():可观察{
const displayDataChanges=[
这个服务数据,
这是我的过滤器更换
];
返回可观察的.merge(…displayDataChanges).map(()=>{
this.filteredData=this.service.data.value.slice().filter((项:TItem)=>{
const searchStr=item.filter.toLowerCase();
返回searchStr.indexOf(this.filter.toLowerCase())!=-1;
});
返回过滤器数据;
});
}
}
通过下面的设置,我可以让它以我最初希望的方式工作。很显然,关键在于向C#对象添加一个filter
属性,该对象用于通过Web API将数据序列化为JSON。不确定为什么需要这样做,因为TypeScript应该能够使用附加功能扩展从Web API接收的模型
简化示例以演示问题集
DemoModel.cs
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
iproperty.interface.ts
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
demo.model.ts
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
core.datasource.ts
Object.defineProperty(exports, "__esModule", { value: true });
var Demo = (function () {
function Demo() {}
Object.defineProperty(Demo.prototype, "filter", {
get: function () { return this.displayName; },
enumerable: true,
configurable: true
});
return Demo;
}());
exports Demo = Demo;
// C# Class JSON is serialized from via Web API
public class DemoModel
{
public string displayName { get; set; }
public string filter
{
get { return displayName; }
}
}
export interface IProperty {
filter: string;
}
import { IProperty } from '../interfaces/iproperty.interface';
export class Demo implements IProperty {
displayName: string;
get filter(): string { return this.displayName; }
}
export class CoreDataSource<TItem extends IProperty> {
filterChange = new BehaviorSubject('');
filteredData: TItem[];
get filter(): string { return this.filterChange.value; }
set filter(filter: string) { this.filterChange.next(filter); }
constructor(private service: IService<TItem>) {
super();
this.filteredData = service.data.value.slice();
}
connect(): Observable<TItem[]> {
const displayDataChanges = [
this.service.data,
this.filterChange
];
return Observable.merge(...displayDataChanges).map(() => {
this.filteredData = this.service.data.value.slice().filter((item: TItem) => {
const searchStr = item.filter.toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
return filteredData;
});
}
}
导出类CoreDataSource{
filterChange=新行为主体(“”);
过滤数据:滴度[];
get filter():字符串{返回this.filterChange.value;}
设置过滤器(过滤器:字符串){this.filterChange.next(过滤器);}
建造商(私人服务:iSeries){
超级();
this.filteredData=service.data.value.slice();
}
connect():可观察{
const displayDataChanges=[
这个服务数据,
这是我的过滤器更换
];
返回可观察的.merge(…displayDataChanges).map(()=>{
this.filteredData=this.service.data.value.slice().filter((项:TItem)=>{
const searchStr=item.filter.toLowerCase();
返回searchStr.indexOf(this.filter.toLowerCase())!=-1;
});
返回过滤器数据;
});
}
}
数据是JSON响应的结果,是一种普通对象和数组的结构,这些对象和数组只有在原型上定义的方法,对象和数组
item
实际上不是一个类实例,也没有它应该具有的filterProperty
方法。因此,指定DemoSource
是不正确的,因为IProperty
应该具有filterProperty
。这愚弄了TypeScript,使其认为对象有这个方法,而它们没有——它们仍然是普通对象,指定的类型不会改变它们
用于泛型的接口应该反映数据结构属性(而不是方法)。对于应该由普通对象构造的类,最好在构造函数中接受普通对象:
export interface IItemData {
displayName: string;
id?: number;
...
}
export class Item implements IItemData {
displayName: string;
constructor({ displayName }: IItemData) {
this.displayName = displayName;
}
filterProperty(): string {
return this.displayName;
}
}
然后应处理数据结构,并将普通项转换为项
实例:
export class DemoSource<TItem extends IItemData> {
...
this.filteredData = this.service.data.value.slice()
.map((item: TItem) => {
// item doesn't have 'filterProperty'
return new Item(item);
})
.filter((item: Item) => {
// item has 'filterProperty'
const searchStr = item.filterProperty().toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
...
导出类DemoSource{
...
this.filteredData=this.service.data.value.slice()
.map((项目:TItem)=>{
//项目没有“filterProperty”
返回新项目(项目);
})
菲菲先生