我用搜索和问题形式寻找建议的问题,但没有找到适合我上下文的解决方案。
最近我注意到,如果不显式地重复类型引用,Typescript就不能从提供的构造函数中检测类型。因此,对于定义为的函数:
export interface IType<T> {
new():T;
}
function useSomeType<T>(ctr:IType<T>, properties:Partial<T>);
我必须写一些东西:
useSomeType<TypeName>(TypeName, {
propName: 1
});
而不是
useSomeType(TypeName, {
propName: 1
});
否则IDE(webstorm)无法检测properties
参数的T
是否为SomeType
,并且无法提供intellicense和建议属性名称。
我必须如何定义useSomeType
的这些参数的类型,才能智能地理解properties
的属性,就像示例中的propName
一样?
更新:
我在Typescript Playground上得到了这个:
https://www.typescriptlang.org/play?#code/MYGwhgzhAEAqCmEAuBhcVoG8CwAoa0AlgCYBc0yAToQHYDmA3HgUoQLbykAiYS8T+aByhg6nCkmr1oAXmgAieQIC+ePLT6UAZmGDxoASVgBPAA7wAPLAB8WZtBrwA7gAoAlKVgq1uPPAAepgD2lEhENJo6eoYA8gBGAFbwwEgQAGK6SCHGdoLAlPC8lrDQAXw0xDBBiclI1i5IZpxGTVbWADTQppRBphCkAApgoYRgIG0eXniqvrgg8GFRWZTGpAbxSSnpmdmyuQT5hXxWpf7lldDVm3UNTQBK8FprJuZtnd29-UMjYxOe+wRoPMwgUkP85I4nNBGuYHlp3AJAdBQQBXSg0aAbWoAOkgEEIdBoLlB7x6fTc0EgcER0BmMx8eCW2WxhyKLgQyDQeM6OEEwggonE8g5SHk0zcQA
class TestClass {
id: string;
time:Date;
message: string = "";
}
interface IType<T> {
new():T;
}
export interface IObjectsFactory {
create<T extends object>(type:IType<T>, props:Partial<T>):T;
}
let factory:IObjectsFactory = {
create<T extends object>(typeRef:IType<T>, props:Partial<T>):T {
let ret:T = new typeRef();
return Object.assign(ret, props) as T;
}
}
factory.create(TestClass, {
message: "Test"
// the properties are listed by playground
});
问题
如果这些是不同的文件(和包),这对我不起作用,比如:
IType<T>
定义在一个包中,确切地说是@sakartvelosoft/types-metadata
。- 接口在一个文件中声明,实现在另一个文件中,测试在第三个文件中。所有这些都在莫诺雷波的内部。
我的声明:
import {CallableIdFactory} from "@sakartvelosoft/id-generation";
import {IType} from "@sakartvelosoft/types-metadata";
export interface EventMetadata {
type: string;
id: string;
timestamp: Date;
source:string;
targets?: string[];
scopeOrModuleId?: string;
preferredChannel?:string;
}
export interface EventDetails<T> extends EventMetadata {
data: T;
}
export interface EventCreationOptions {
source?: string;
targets?:string[];
scopeOrModuleId?: string;
preferredChannel?:string;
}
export interface IEventsFactoryOptions {
eventIdFactory?:CallableIdFactory;
source?:string;
targets?:string[];
targetsCleanup?:(eventType: string, source:string, targets:string[]) => string[];
}
export interface IEventFactoryEntry<T extends object> {
createEvent(data:Partial<T>, options?:EventCreationOptions):EventDetails<T>;
rebuildEvent(eventMetadata:EventMetadata, data:object):EventDetails<T>;
}
export interface IEventsFactory {
registerEventsType<T extends object>(eventType:IType<T>, typeAlias?:string):void;
forEvent<T extends object>(eventType: IType<T>):IEventFactoryEntry<T>;
forEventByAlias<T extends object>(eventTypeAlias:string):IEventFactoryEntry<T>;
createEvent<T>(typeDef:IType<T>, data:Partial<T>, options?:EventCreationOptions):EventDetails<T>;
rebuildEvent(eventMetadata:EventMetadata, data:object):EventDetails<T>;
}
测试:
import {describe} from "mocha";
import {createEventsFactory} from "../src";
import {createTypesRegistry} from "@sakartvelosoft/types-metadata";
import {expect} from "chai";
describe('Test events construction and rebuilding', () => {
class TestEvent {
message: string;
}
it('Construct event', () => {
const eventFactory = createEventsFactory(createTypesRegistry(), { source: 'test' });
eventFactory.registerEventsType(TestEvent, 'test-event');
const newEvent = eventFactory.createEvent(TestEvent, {
message: "Demo"
});
expect(newEvent.data).haveOwnProperty('test');
expect(newEvent.data).instanceof(TestEvent);
expect(newEvent.data.test).eql('Demo');
})
})
更新2:
(几乎)提到的代码似乎在TSFiddle中按预期工作(TestEvent的属性被识别/理解/列出),但在WebStorm项目中却不是,如果我理解正确的话,这是非常奇怪的,Webstorm不能正确地推断类型,而TSFiddle可以。
TSFiddle链接:https://stackblitz.com/edit/tsfiddle-quxumi?file=src%2Fapp%2Finterfaces.ts,src%2Fapp%2Ftest-code.ts,src%2Fapp%2Fstubs.ts
更新3
正如我所看到的,由于TSFiddle没有显式的tsconfig.json
文件,并且它们使用了一些内置的“配置”,我在我的项目的根目录下提供了tsconfig
,在那里我经历了以下情况:
{
"compilerOptions": {
"module": "CommonJS",
"target": "ES2021",
"lib": ["ES2021"],
"sourceMap": true,
"outDir": "./dist",
"declaration": true
},
"include": ["./src/**/*.ts", "./tests/**/*.ts"],
"compileOnSave": true,
"exclude": [
"node_modules"
]
}
.eslintrc.js
:
/* eslint-env node */
module.exports = {
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
root: true,
};
package.json
中的dev-dependencies列表:
{
"devDependencies": {
"@types/chai": "^4.3.5",
"@types/mocha": "^10.0.1",
"@types/node": "^18.16.3",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"chai": "^4.3.7",
"eslint": "^8.39.0",
"mocha": "^10.2.0",
"ts-mocha": "^10.0.0",
"typescript": "^5.0.4"
}
}
解决方案
在进一步研究问题原因和影响配置和问题之后,我发现从TypeScript版本(如最新的5.0.2
)降级到旧版本(如4.8.4
)似乎可以解决问题。尽管如此,希望它将被修复与5.0.2
类型脚本版本,我添加了一个相关的错误在他们的(网络 Storm )跟踪器。
将关闭此问题,因为有可用的解决方法。
1条答案
按热度按时间xwbd5t1u1#
解决方案
在进一步研究问题原因和影响配置和问题之后,我发现从TypeScript版本(如最新的
5.0.2
)降级到旧版本(如4.8.4
)似乎可以解决问题。尽管如此,希望它将被修复与5.0.2 typescript 版本,我添加了一个相关的错误在他们的(网络 Storm )跟踪。将关闭此问题,因为有可用的解决方法。