我正在尝试在 Typescript 中定义一些通用函数类型。似乎有两种类似的方法可以做到这一点,而且它们都有效。然而,第二种形式 - 见下文ConcatY- 似乎并不那么灵活,或者至少我不知道如何指示函数采用具有特定参数类型的其中之一。有没有办法定义一个接受ConcatY数字的函数?一般来说,我应该如何考虑这两种定义泛型函数的方法之间的差异?
// Two similar looking function types
type ConcatX<T> = (a: T, b: T) => T;
type ConcatY = <T>(a: T, b: T) => T;
// Can create instances of each of these types
const sum: ConcatX<number> = (a, b) => a + b;
const product: ConcatY = (a: number, b: number) => a + b;
// Can define a function that takes a ConcatX
function DoMathX(sum: ConcatX<number>) {
console.log(`1 + …Run Code Online (Sandbox Code Playgroud) 我在另一个 NPM 包中有一个 NPM 包。子包有一些代码,例如import { range } from 'iter-tools'. 即使子 package.json 不依赖于iter-tools,我也没有收到任何类型的 Typescript 编译错误。据推测,这是因为模块解析器 / tsc 正在走到父node_modules文件夹以查找依赖项并在那里找到它。我不希望这种情况发生。我想得到一个错误,我忘记将其包含iter-tools在本地子项的依赖项列表中。换句话说,我希望子包在某种程度上是独立的。我不知道如何实现这一点。我做了很多谷歌搜索,发现了类似的问题,但找不到答案。有什么我需要添加tsconfig.json或package.json?
这个问题的背景是我有一个 Angular + Firebase 存储库。服务器部分之一是 Firebase 云功能 - FCF。这生活在一个functions具有自己的 package.json 的文件夹中,并且这是 Angular CLI 设置的项目的子文件夹。我在部署 FCF 时遇到了麻烦,除非它所需的所有代码都包含在 FCF 文件夹中。如果在更高级别的 node_modules 文件夹(例如 Angular 根目录中)中获取某些代码和类型定义,则部署将无法进行。如果我忘记在 FCF 的 package.json 中包含依赖项,我会收到编译错误。相反,我没有收到任何编译错误,只有部署错误。
我的项目还有一个本地 NPM 包,其中包含在客户端和服务器之间共享的代码,我想确保该包是独立的 - 不依赖于父文件夹中的 package.json 文件。
我这里有一个简单的程序,可以显示不同单词中的字母数。它按预期工作。
static void Main(string[] args) {
var word = new Subject<string>();
var wordPub = word.Publish().RefCount();
var length = word.Select(i => i.Length);
var report =
wordPub
.GroupJoin(length,
s => wordPub,
s => Observable.Empty<int>(),
(w, a) => new { Word = w, Lengths = a })
.SelectMany(i => i.Lengths.Select(j => new { Word = i.Word, Length = j }));
report.Subscribe(i => Console.WriteLine($"{i.Word} {i.Length}"));
word.OnNext("Apple");
word.OnNext("Banana");
word.OnNext("Cat");
word.OnNext("Donkey");
word.OnNext("Elephant");
word.OnNext("Zebra");
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
输出是:
Apple 5
Banana 6
Cat 3
Donkey 6
Elephant 8 …Run Code Online (Sandbox Code Playgroud) 我喜欢使用对象字面量作为函数参数,因为它允许我标记参数名称。我认为会有一种类型安全的通用方法来对这些类型的函数进行部分函数应用。假设一个函数接受一个类型为 X 的参数。然后我通过另一个名为“partial”的函数运行该函数,其中我提供了 X 的 Partial,它可以返回一个只需要缺失值的新函数。最容易看下面的例子。这里的好处是,通过我的“部分”函数,我可以提供任意数量的参数或参数组合,并获得一个结果函数,该函数清楚地表明仍然需要什么。
function partial<Args, Fixed extends Partial<Args>, Result>(fn: (args: Args) => Result, fixed: Fixed) {
type Unspecified = { [P in Exclude<keyof Args, keyof Fixed>]: Args[P] };
const result = (args: Unspecified) => {
const combined = {};
Object.assign(combined, fixed, args);
return fn(combined as Args);
};
return result as ({} extends Unspecified ? () => Result : (args: Unspecified) => Result);
}
interface AddThreeNumbersArgs {
a: number;
b: number;
c: number;
caption: string;
}
function addThreeNumbers(args: …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一些克隆对象但更改深层属性的实用函数。
这是一个有点无用的版本的示例,它只是用可能属于不同类型的其他值替换对象的命名属性。该代码有效 - 它用新值替换了命名属性 - 但由于某种原因 TypeScript 无法确定所创建对象的类型并给出编译错误。为什么 TypeScript 不这样,我怎样才能让它工作?
我可以显式定义返回类型 - 但是对于该函数的版本来说,这会变得很尴尬,该版本会深度更改属性几个级别。
it('change type of input object', () => {
const cloneWith = <T extends Record<string, unknown>, A extends keyof T, V>(
i: T,
a: A,
value: V
) => ({
...i,
[a]: value,
});
const source = { name: 'bob', age: 90 };
const result = cloneWith(source, 'age', 'old!');
// This test passes
expect(result.age).to.equal('old!');
// But compile error - number and string have no overlap -
// on …Run Code Online (Sandbox Code Playgroud) 我正在浏览 F# 文档,想知道 Option 模块中的“缺失”函数。有一个map2需要两个选项并且似乎logical AND对它做了一个。如果其中一个为 None,则结果为 None。否则,如果您有 Some(a) 和 Some(b),它将返回 Some(f(a,b))。
功能在哪里logical OR?我期望有一个类似的函数,如果只有一个是 Some,则返回它。但如果两者都是 Some,它会像逻辑 AND 情况一样执行 Some(f(a,b)) 。我可以手动写出来,模式匹配没有问题。
let concat f a b =
match a, b with
| Some(a), Some(b) -> Some(f a b)
| Some(a), None -> Some(a)
| None, Some(b) -> Some(b)
| _ -> None
Run Code Online (Sandbox Code Playgroud)
实际上,如果您有一个可选数字列表并且想要将它们相加,这可能很有用。如果列表为空或仅包含“无”值,则答案为“无”。None 不会影响结果,就像零一样。或者是几个可选的字符串,并且您想要将它们连接起来。
我假设由于 F# 在标准库中似乎没有这个函数,所以我一定是以错误的方式思考问题的。或者有更简洁的方法吗?