Inferring Function Parameter Types
Example 1

I try to understand eventType field from Event object. But in order to use createEventGridMessage in other TypeScript file, you need to import StartEvent, InfoEvent and EndEvent types. So next example of this case looks better to me 🙂
import {v4 as uuidv4} from 'uuid';
export type BaseEvent = {
timeStamp?: number,
componentName: string,
componentVersion: string,
operationId: string,
correlationId: string,
data: any,
}
export type StartEvent = Partial<BaseEvent> & {
eventType: 'LogStart',
source: string,
trigger: string,
};
export type EndEvent = Partial<BaseEvent> & {
eventType: 'LogEnd'
destination: 'Event Grid' | 'Http Response' | 'Database' | string,
};
export type InfoEvent = Pick<EndEvent, keyof Omit<EndEvent, 'eventType'>> & { eventType: 'LogInfo' };
export type Event = StartEvent | EndEvent | InfoEvent;
export type EventGridMessageParameters<T extends Event> = Pick<EventGridMessage<T>, 'data' | 'eventType' | 'subject' | 'topic'>;
export type EventType<T extends Event> = T extends StartEvent ? 'LogStart' : T extends EndEvent ? 'LogEnd' : T extends InfoEvent ? 'LogInfo' : 'UNKNOWN EVENT TYPE';
export interface EventGridMessage<T extends Event> {
id: string;
topic: string;
subject: string;
eventType: EventType<T>;
eventTime: Date;
data: T;
dataVersion: string;
metadataVersion: string;
}
export const createEventGridMessage = <T extends Event>({
data,
eventType,
subject = "New message from unknown source",
topic = ""
}: EventGridMessageParameters<T>): EventGridMessage<T> =>
({
id: uuidv4(),
topic,
subject,
eventType,
eventTime: new Date(),
data: {...data, timeStamp: data.timeStamp || new Date().getTime()},
dataVersion: "1.0",
metadataVersion: "1.0"
});
const startLogMessage = createEventGridMessage<StartEvent>({
eventType: 'LogStart',
data: {
eventType: 'LogStart',
trigger: '',
source: '',
correlationId: '',
componentVersion: '',
componentName: '',
operationId: ''
},
subject: '',
topic: ''
});
console.log(startLogMessage);
const infoLogMessage = createEventGridMessage<InfoEvent>({
eventType: 'LogInfo',
data: {
eventType: 'LogInfo',
correlationId: '',
componentVersion: '',
componentName: '',
operationId: '',
destination: '',
},
subject: '',
topic: ''
});
console.log(infoLogMessage);
const endLogMessage = createEventGridMessage<EndEvent>({
eventType: 'LogEnd',
data: {
eventType: 'LogEnd',
timeStamp: new Date().getTime(),
correlationId: '',
componentVersion: '',
componentName: '',
operationId: '',
destination: '',
},
subject: '',
topic: ''
});
console.log(endLogMessage);
Continue reading SomeType extends OtherType ? TrueType : FalseType;
type NumberOrNot<T> = T extends number ? string : never;
type StringOrNot<T> = T extends string ? string : never;
type BooleanOrNumberOnly<T> = T extends boolean | number ? T : never;
type NewType = StringOrNumberOnly<string | number | boolean>;
const a1: NewType = true; // boolean
const a2: NewType = 23; // number
Continue reading const mockedPutObject = jest.fn();
jest.mock('@aws-sdk/client-s3', () => {
return {
S3: jest.fn(() => ({
putObject: () => mockedPutObject()
}))
}
});
jest.mock('uuid', () => ({ v4: () => '00000000-0000-0000-0000-000000000000' }));
jest.mock('uuid');
const mockedUuidv4 = uuidv4 as jest.Mock;
mockedUuidv4.mockReturnValue('00000000-0000-0000-0000-000000000000');
const mockedAjvValidate = jest.fn().mockReturnValue(true);
jest.mock('ajv', () => {
return jest.fn(() => ({
compile: () => () => mockedAjvValidate()
}))
});
jest.mock('moment', () => () => ({ format: () => '30-12-2021' }));
import { v4 as uuid } from 'uuid';
export interface IEvent {
id?: string;
eventType: string;
data: any;
}
export interface IEventRepository {
getEvent(id: string): IEvent | undefined;
setEvent(event: IEvent): IEvent;
}
const createEvent = (event: IEvent): IEvent => ({ id: uuid(), ...event });
export class EventRedisRepository implements IEventRepository {
constructor(private events: Array<IEvent> = []) { }
getEvent(id: string): IEvent | undefined {
return this.events.find(item => item.id === id);
}
setEvent(event: IEvent): IEvent {
const newEvent: IEvent = createEvent(event);
this.events.push(newEvent);
return newEvent;
}
}
export class EventCosmosDbRepository implements IEventRepository {
constructor(private events: Array<IEvent> = []) { }
getEvent(id: string): IEvent | undefined {
return this.events.find(item => item.id === id);
}
setEvent(event: IEvent): IEvent {
const newEvent: IEvent = createEvent(event);
this.events.push(newEvent);
return newEvent;
}
}
import { Persister } from '../src';
import { EventRedisRepository, EventCosmosDbRepository, IEventRepository, IEvent } from './sample';
const mockedRedisGetEvent = jest.fn();
const mockedRedisSetEvent = jest.fn();
const mockedCosmosdbGetEvent = jest.fn();
const mockedCosmosdbSetEvent = jest.fn();
jest.mock('./sample', () => {
return {
EventRedisRepository: jest.fn(() => ({
getEvent: () => mockedRedisGetEvent(),
setEvent: () => mockedRedisSetEvent(),
})),
EventCosmosDbRepository: jest.fn(() => ({
getEvent: () => mockedCosmosdbGetEvent(),
setEvent: () => mockedCosmosdbSetEvent(),
})),
}
});
const eventRedisRepository = new EventRedisRepository();
const eventCosmosdbRepository = new EventCosmosDbRepository();
const module_name = `${Persister.name}`;
describe(`${module_name} Test`, () => {
it('should call setEvent function in both persisters', () => {
const eventPersister = new Persister<IEventRepository>([eventRedisRepository, eventCosmosdbRepository]);
const eventId = '4e0c71bb-eedf-43dd-b9a1-911a7ed6d74f';
const newEvent: IEvent = { id: eventId, eventType: 'Submission', data: {} };
eventPersister.set('setEvent', op => op(newEvent));
expect(mockedRedisSetEvent).toHaveBeenCalledTimes(1);
expect(mockedCosmosdbSetEvent).toHaveBeenCalledTimes(1);
});
});
import { Persister } from '../src';
import { EventRedisRepository, EventCosmosDbRepository, IEventRepository, IEvent } from './sample';
import { mocked } from 'jest-mock'
jest.mock('./sample');
const eventRedisRepository = new EventRedisRepository();
const eventCosmosdbRepository = new EventCosmosDbRepository();
const mockedEventRedisRepository = mocked(eventRedisRepository, true);
const mockedEventCosmosdbRepository = mocked(eventRedisRepository, true);
const module_name = `${Persister.name}`;
describe(`${module_name} Test`, () => {
it('should call setEvent function in both persisters', () => {
const eventPersister = new Persister<IEventRepository>([eventRedisRepository, eventCosmosdbRepository]);
const eventId = '4e0c71bb-eedf-43dd-b9a1-911a7ed6d74f';
const newEvent: IEvent = { id: eventId, eventType: 'Submission', data: {} };
eventPersister.set('setEvent', op => op(newEvent));
expect(mockedEventRedisRepository.setEvent).toHaveBeenCalledTimes(1);
expect(mockedEventCosmosdbRepository.setEvent).toHaveBeenCalledTimes(1);
});
});



https://github.com/nodejs-projects-kenanhancer/typescript-object-oriented-programming
See the Pen TypeScriptOOPDemo1 by kenanhancer (@kenanhancer) on CodePen.
$ mkdir typescript-demo1
$ npm init -y
$ npm install --save-dev typescript @types/node rimraf
$ npx tsc --init --rootDir src --outDir build \
--esModuleInterop --resolveJsonModule --lib es6 \
--module commonjs --allowJs true --noImplicitAny true
$ mkdir src
$ echo "console.log('Hello world');" > src/index.ts
$ npx tsc
$ node dist/index.js
Continue reading See the Pen TypeScriptInterfaceDemo1 by kenanhancer (@kenanhancer) on CodePen.
Continue readingThis post is just a reminder for me. So in order to find more details about dotnet CLI, follow the below link
https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet
$ dotnet new console -h
Console App (C#)
Author: Microsoft
Description: A project for creating a command-line application that can run on .NET on Windows, Linux and macOS
Usage:
dotnet new console [options] [template options]
Options:
-n, --name <name> The name for the output being created. If no name is specified, the name of the output directory is used.
-o, --output <output> Location to place the generated output.
--dry-run Displays a summary of what would happen if the given command line were run if it would result in a template creation.
--force Forces content to be generated even if it would change existing files.
--no-update-check Disables checking for the template package updates when instantiating a template.
--project <project> The project that should be used for context evaluation.
-lang, --language <C#> Specifies the template language to instantiate.
--type <project> Specifies the template type to instantiate.
Template options:
-f, --framework <net5.0|net6.0|net7.0> The target framework for the project.
Type: choice
net7.0 Target net7.0
net6.0 Target net6.0
net5.0 Target net5.0
Default: net7.0
--langVersion <langVersion> Sets the LangVersion property in the created project file
Type: text
--no-restore If specified, skips the automatic restore of the project on create.
Type: bool
Default: false
--use-program-main Whether to generate an explicit Program class and Main method instead of top-level statements.
Type: bool
Default: false
To see help for other template languages (F#, VB), use --language option:
dotnet new console -h --language F#
$ dotnet new --list
These templates matched your input:
Template Name Short Name Language Tags
-------------------------------------------- ------------------ ---------- --------------------------------
ASP.NET Core Empty web [C#],F# Web/Empty
ASP.NET Core gRPC Service grpc [C#] Web/gRPC
ASP.NET Core Web API webapi [C#],F# Web/WebAPI
ASP.NET Core Web App webapp,razor [C#] Web/MVC/Razor Pages
ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC
ASP.NET Core with Angular angular [C#] Web/MVC/SPA
ASP.NET Core with React.js react [C#] Web/MVC/SPA
ASP.NET Core with React.js and Redux reactredux [C#] Web/MVC/SPA
Blazor Server App blazorserver [C#] Web/Blazor
Blazor Server App Empty blazorserver-empty [C#] Web/Blazor/Empty
Blazor WebAssembly App blazorwasm [C#] Web/Blazor/WebAssembly/PWA
Blazor WebAssembly App Empty blazorwasm-empty [C#] Web/Blazor/WebAssembly/PWA/Empty
Class Library classlib [C#],F#,VB Common/Library
Console App console [C#],F#,VB Common/Console
dotnet gitignore file gitignore Config
Dotnet local tool manifest file tool-manifest Config
EditorConfig file editorconfig Config
global.json file globaljson Config
MSBuild Directory.Build.props file buildprops MSBuild/props
MSBuild Directory.Build.targets file buildtargets MSBuild/props
MSTest Test Project mstest [C#],F#,VB Test/MSTest
MVC ViewImports viewimports [C#] Web/ASP.NET
MVC ViewStart viewstart [C#] Web/ASP.NET
NuGet Config nugetconfig Config
NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit
NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit
Protocol Buffer File proto Web/gRPC
Razor Class Library razorclasslib [C#] Web/Razor/Library
Razor Component razorcomponent [C#] Web/ASP.NET
Razor Page page [C#] Web/ASP.NET
Solution File sln,solution Solution
Web Config webconfig Config
Worker Service worker [C#],F# Common/Worker/Web
xUnit Test Project xunit [C#],F#,VB Test/xUnit
$ dotnet --list-sdks
5.0.408 [/Users/kenanhancer/.dotnet/sdk]
6.0.411 [/Users/kenanhancer/.dotnet/sdk]
7.0.305 [/Users/kenanhancer/.dotnet/sdk]
Use any template short name after dotnet net and .NET SDK version after --framework option.
$ dotnet new console --framework net6.0 -o console-demo1
$ dotnet new webapi --framework net6.0 -o webapi-todo-demo1
If you have multiple versions of the .NET Core SDK installed, the version that's used can be controlled using a global.json file. This file allows you to specify which version of the .NET Core SDK should be used.
$ dotnet new globaljson --sdk-version 6.0.411 --force
-o or –output is location to place for new generated project.
$ dotnet new console --framework net6.0 --output enum_demo4
# OR
$ dotnet new console --framework net6.0 -o enum_demo4
# OR
$ dotnet new console --framework net6.0 --name enum_demo4


