1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

fix(npm): improve exports resolution when type checking (#17071)

Closes #17012
This commit is contained in:
David Sherret 2022-12-15 21:15:25 -05:00 committed by GitHub
parent 28cc18b516
commit 9e977cd6aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 76 additions and 18 deletions

View file

@ -522,7 +522,7 @@ pub fn node_resolve_npm_reference(
npm_resolver,
)
.with_context(|| {
format!("Error resolving package config for '{}'.", reference)
format!("Error resolving package config for '{}'", reference)
})?;
let resolved_path = match maybe_resolved_path {
Some(resolved_path) => resolved_path,

View file

@ -279,7 +279,7 @@ mod npm {
exit_code: 1,
});
itest!(types {
itest!(types_general {
args: "check --quiet npm/types/main.ts",
output: "npm/types/main.out",
envs: env_vars_for_npm_tests(),

View file

@ -0,0 +1 @@
export function getClient(): 5;

View file

@ -0,0 +1,3 @@
export function getClient() {
return 5;
}

View file

@ -0,0 +1 @@
export function entryC(): 12;

View file

@ -0,0 +1,3 @@
export function entryC() {
return 12;
}

View file

@ -0,0 +1,2 @@
// it will go to this and not the types entry because this entry was first
export function entryB(): string;

View file

@ -0,0 +1,19 @@
{
"name": "@denotest/types-exports-subpaths",
"version": "1.0.0",
"exports": {
"./client": {
"types": {
"default": "./client.d.ts"
},
"import": "./dist/client.mjs"
},
"./entry-b": {
"import": "./entry-b.d.ts",
"types": "./dist/entry-b-wrong.d.ts"
},
"./entry-c": {
"import": "./dist/entry-c.js"
}
}
}

View file

@ -1,7 +1,7 @@
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
bar: 1,
~~~
at [WILDCARD]/npm/types/main.ts:7:3
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
The expected type comes from property 'bar' which is declared here on type 'Foobar'
bar: string;
@ -11,7 +11,7 @@ error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
prop: 1,
~~~~
at [WILDCARD]/npm/types/main.ts:11:3
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
The expected type comes from property 'prop' which is declared here on type 'SomeInterface'
prop: string;
@ -21,7 +21,7 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
prop2: "asdf",
~~~~~
at [WILDCARD]/npm/types/main.ts:12:3
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
The expected type comes from property 'prop2' which is declared here on type 'SomeInterface'
prop2: number;
@ -31,7 +31,7 @@ TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
fizz: 1,
~~~~
at [WILDCARD]/npm/types/main.ts:16:3
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
The expected type comes from property 'fizz' which is declared here on type 'Fizzbuzz'
fizz: string;
@ -41,11 +41,26 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
buzz: 2,
~~~~
at [WILDCARD]/npm/types/main.ts:17:3
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
The expected type comes from property 'buzz' which is declared here on type 'Fizzbuzz'
buzz: string;
~~~~
at [WILDCARD]/@denotest/types/1.0.0/index.d.ts:3:3
Found 5 errors.
TS2322 [ERROR]: Type '5' is not assignable to type '"test1"'.
const valueA: "test1" = getClient();
~~~~~~
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
TS2322 [ERROR]: Type 'string' is not assignable to type '"test2"'.
const valueB: "test2" = entryB();
~~~~~~
at [WILDCARD]/types/main.ts:[WILDCARD]
TS2322 [ERROR]: Type '12' is not assignable to type '"test3"'.
const valueC: "test3" = entryC();
~~~~~~
at [WILDCARD]/types/main.ts:[WILDCARD]
Found 8 errors.

View file

@ -1,6 +1,9 @@
import type { Fizzbuzz } from "npm:@denotest/types";
import type { SomeInterface } from "npm:@denotest/types_imported";
import type { Foobar as FooInterface } from "npm:@denotest/types_imported/subpath";
import { getClient } from "npm:@denotest/types-exports-subpaths/client";
import { entryB } from "npm:@denotest/types-exports-subpaths/entry-b";
import { entryC } from "npm:@denotest/types-exports-subpaths/entry-c";
const foobar: FooInterface = {
foo: "foo",
@ -16,3 +19,7 @@ const fizzbuzz: Fizzbuzz = {
fizz: 1,
buzz: 2,
};
const valueA: "test1" = getClient();
const valueB: "test2" = entryB();
const valueC: "test3" = entryC();

View file

@ -1,5 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use std::path::PathBuf;
use deno_core::error::generic_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
@ -61,13 +63,26 @@ pub fn err_invalid_package_target(
) -> AnyError {
let rel_error = !is_import && !target.is_empty() && !target.starts_with("./");
let mut msg = "[ERR_INVALID_PACKAGE_TARGET]".to_string();
let pkg_json_path = PathBuf::from(pkg_path).join("package.json");
if key == "." {
assert!(!is_import);
msg = format!("{} Invalid \"exports\" main target {} defined in the package config {}package.json", msg, target, pkg_path)
msg = format!(
"{} Invalid \"exports\" main target {} defined in the package config {}",
msg,
target,
pkg_json_path.display()
)
} else {
let ie = if is_import { "imports" } else { "exports" };
msg = format!("{} Invalid \"{}\" target {} defined for '{}' in the package config {}package.json", msg, ie, target, key, pkg_path)
msg = format!(
"{} Invalid \"{}\" target {} defined for '{}' in the package config {}",
msg,
ie,
target,
key,
pkg_json_path.display()
)
};
if let Some(base) = maybe_referrer {

View file

@ -502,14 +502,6 @@ fn resolve_package_target(
{
let condition_target = target_obj.get(key).unwrap().to_owned();
if mode.is_types()
&& key.as_str() != "types"
&& condition_target.is_string()
{
// skip because this isn't a types entry
continue;
}
let resolved = resolve_package_target(
package_json_path,
condition_target,