Add types for namespace-js (#65576)

* add namespace-js type

* validate fix

* fix to object type

* fix version

* delete patch version

* improve types

* add dot object type
This commit is contained in:
kuromoka
2023-06-06 09:40:05 +09:00
committed by GitHub
parent d6901b61b3
commit 9007ae08f6
4 changed files with 137 additions and 0 deletions

52
types/namespace-js/index.d.ts vendored Normal file
View File

@@ -0,0 +1,52 @@
// Type definitions for namespace-js 0.0
// Project: https://github.com/hirokidaichi/namespace-js
// Definitions by: kuromoka <https://github.com/kuromoka>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
export as namespace Namespace;
export namespace NamespaceJs {
type UserObject = object;
type Fqn = string;
type ImportName = string;
// if you don't attach anything in use() function, ns is this type.
type DotUserObject<Fqn, UserObject> = Fqn extends `${infer Fqn1}.${infer Fqn2}`
? {
[P in Fqn1]: DotUserObject<Fqn2, UserObject>;
}
: {
[P in Extract<Fqn, string>]: {
[P in keyof UserObject]: UserObject[P];
};
};
interface Definition<T extends UserObject> {
define(
callback: (
ns: T & {
// eslint-disable-next-line no-unnecessary-generics
provide: <U extends UserObject>(obj: U) => void;
},
) => void,
): void;
}
interface Application<T extends UserObject> {
use<U extends UserObject, Syntax>(
syntax: Syntax,
): Syntax extends `${Fqn} ${ImportName}`
? Application<T & U>
: Syntax extends string
? Application<DotUserObject<Syntax, T & U>>
: never;
apply(callback: (ns: T) => void): void;
}
}
declare global {
// eslint-disable-next-line no-unnecessary-generics
function Namespace<T extends NamespaceJs.UserObject>(fqn: NamespaceJs.Fqn): NamespaceJs.Definition<T>;
}
export const use: NamespaceJs.Application<{}>['use'];
export const apply: NamespaceJs.Application<{}>['apply'];

View File

@@ -0,0 +1,61 @@
import * as Namespace from 'namespace-js';
interface UserObject1 {
foo: () => string;
bar: () => string;
}
interface UserObject2 {
baz: () => string;
}
Namespace('com.example.application').define(ns => {
ns.provide<UserObject1>({
foo() {
return 'foo';
},
bar() {
return 'bar';
},
});
});
Namespace<UserObject1>('com.example.application').define(ns => {
// $ExpectType string
ns.bar();
// $ExpectType string
ns.bar();
ns.provide<UserObject2>({
baz() {
return 'baz';
},
});
});
Namespace.use<UserObject1, 'com.example.application foo,bar'>('com.example.application foo,bar')
.use<UserObject2, 'com.example.application baz'>('com.example.application baz')
.apply(ns => {
// $ExpectType UserObject1 & UserObject2
ns;
// $ExpectType string
ns.foo();
// $ExpectType string
ns.bar();
// $ExpectType string
ns.baz();
// @ts-expect-error
ns.qux();
});
Namespace.use<UserObject1, 'com.example.application'>('com.example.application')
.use<UserObject2, 'com.example.application baz'>('com.example.application baz')
.apply(ns => {
// $ExpectType string
ns.com.example.application.foo();
// $ExpectType string
ns.com.example.application.bar();
// $ExpectType string
ns.baz();
// @ts-expect-error
ns.qux();
});

View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"namespace-js-tests.ts"
]
}

View File

@@ -0,0 +1 @@
{ "extends": "@definitelytyped/dtslint/dt.json" }