gpt4 book ai didi

typescript - 如何在 Typescript 中测试泛型类型?不是泛型类型的实现,而是作为类型保护?

转载 作者:行者123 更新时间:2023-12-03 21:11:38 28 4
gpt4 key购买 nike

我正在将一堆 typescript 类型扩展到实用程序库中,作为个人“我真的了解 typescript 吗?”项目。

我只是在弄清楚如何对这该死的东西进行单元测试时遇到了很多麻烦。

问题是我想测试当我将错误的类型传递给调用类型的函数时,TSC 是否会捕获它。它的作用。辉煌。但是有一个很小的缺陷,因为我使用的单元测试库 (Jest) 会抛出一个错误(所需的行为),然后拒绝运行测试套件的其余部分,因为它抛出了一个错误。我什至不能使用“会抛出错误”,因为它不是 Javascript 错误而是 Typescript 错误。

这是我到目前为止的代码。我正在使用 Jest,但我的解决方案不需要特定于 Jest,我有一种有趣的感觉,我可能需要某种专门的测试库。

// src/Either/Either.ts
export type Either<Base, Either, Or> = (Base & Either) | (Base & Or);

// src/either/Either.spec.ts

import { Either } from "./Either";

interface Pet {
name: string;
}
interface Dog {
says: "awoo" | "ruff" | "yip" | "bork" | "bark" | "grr";
willFetch: true;
}
interface Cat {
says: "meow" | "hiss";
willFetch: false;
}

describe("Either<Base, Either, Or>", () => {
it("allows one extension OR the other, but not both, and not neither", () => {
type CommonPet = Either<Pet, Dog, Cat>;
const whatAmI = (pet: CommonPet): "dog" | "cat" => {
if (pet.willFetch === true) {
return "dog";
}
return "cat";
};
expect(whatAmI({ name: "Rex", willFetch: true, says: "awoo" })).toBe("dog");
expect(whatAmI({ name: "Psycho", says: "hiss", willFetch: false })).toBe(
"cat"
);
// these lines will throw a typescript error (desired)
/*
const freak = whatAmI({ name: "Freak", says: "meow", willFetch: true });
const uncommonPet = whatAmI({ name: "Nagini", says: 'hiss', willFetch: false, isSnake: true });
*/

// but how to I tell Jest that I WANT it to throw a typescript error?
interface AristoCat {
knowsWhereItsAt: boolean;
}
interface JellicleCat {
nightmareFuel: number;
}
type MusicalCat = Either<Pet & Cat, AristoCat, JellicleCat>;
const isGood = (cat: MusicalCat): boolean | never => {
if ("knowsWhereItsAt" in cat) {
return true;
}
if (cat.nightmareFuel > 0) {
throw new Error("NOOOOOO!");
}
return false;
};
expect(
isGood({
name: "Duchess",
says: "meow",
willFetch: false,
knowsWhereItsAt: true
})
).toBe(true);
expect(
isGood({
name: "MacCavity (stage)",
willFetch: false,
says: "meow",
nightmareFuel: 0
})
).toBe(false);
const filmIt = () =>
isGood({
name: "MacCavity",
willFetch: false,
says: "meow",
nightmareFuel: 9001
});
expect(filmIt).toThrowErrorMatchingInlineSnapshot(`"NOOOOOO!"`);

// again, we expect this to throw in TYPESCRIPT because it has BOTH.
/*
const dreamIHadOnAcid = isGood({
name: 'Cheshire',
says: 'meow',
willFetch: false,
knowsWhereItsAt: true,
nightmareFuel: 5/7
})
*/
// again, we expect this to throw in TYPESCRIPT because it has NEITHER.
/*
const dreamIHadOnAcid = isGood({
name: 'Tardar Sauce',
says: 'meow',
willFetch: false,
})
*/
});
});

- 编辑:

还有一个额外的困难。因为我不确定我的任一种类型是否按照它应该的方式工作(或者如果是,编译器无法接收它。)

我正在为此使用 Typescript 游乐场...
export type Either<Base, Either, Or> = (Base & Either) | (Base & Or);

type Pet = {
name: string;
says?: string;
}
type DogExtension = {
playHours: number;
}
type CatExtension = {
sleepHours: number;
}

type CommonPet = Either<Pet, DogExtension, CatExtension>;

const dog: CommonPet = { name: "rex", says: "awoo", playHours: 5 };
const cat: CommonPet = { name: "manx", says: "meow", sleepHours: 14 };

const testPet = (testName: string, pet: CommonPet): CommonPet => {
return pet
};

testPet("dog should pass", dog);
testPet("cat should pass", cat);
testPet("catdog should not pass", { ...dog, ...cat }); /* should throw a type error, but doesn't */

这可能是 typescript 编译器中的一个错误……而且很容易制作。狗是普通宠物,猫是普通宠物,那么为什么 {...dog, ...cat} 不是普通宠物?除非 - 更有可能的解决方案,我的要么 =(T&E) | (T&O) 只是不像我想象的那样工作。

最佳答案

我之前遇到过这个问题并设法让它与 dtslint 一起工作.我发现这些测试对于编写包含大量泛型类型逻辑的库非常有值(value),因为我经常遇到修复一件事会导致其他地方错误推断类型的情况。

这是the repo我设法让它工作的地方。具体来说,this file包含其中一项测试。可以使用 yarn type-check 运行类型测试或 npm run type-check .

当某些事情失败时,您会收到如下错误:

Error: /good-form/types/Field.types.ts:19:3
ERROR: 19:3 expect TypeScript@local expected type to be:
number
got:
string

关于typescript - 如何在 Typescript 中测试泛型类型?不是泛型类型的实现,而是作为类型保护?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59494889/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com