text:
Negated types

Long have we spoken of them in hushed tones and referenced them in related issues, here they are:
Negated Types
Negated types, as the name may imply, are the negation of another type. Conceptually, this means that if string covers all values which are strings at runtime, a "not string" covers all values which are... not. We had hoped that conditional types would by and large subsume any use negated types would have... and they mostly do, except in many cases we need to apply the constraint implied by the conditional's check to it's result. In the true branch, we can just intersect the extends clause type, however in the false branch we've thus far been discarding the information. This means unions may not be filtered as they should (especially when conditionals nest) and information can be lost. So that ended up being the primary driver for this primitive - it's taking what a conditional type false branch implies, and allowing it to stand alone as a type.
Syntax
not T

where T is another type. I'm open to bikeshedding this, or even shipping without syntax available, but among alternatives (!, ~) not reads pretty well.
Identities
These are little tricks we do on negated type construction to help speed things along (and give negations on algebraic types canonical forms).

not not T is T
not (A | B | C | ...) is not A & not B & not C & not ...
not (A & B & C & ...) is not A | not B | not C | not ...
not unknown is never
not never is unknown
not any is any (since any is the NaN of types and behaves as both the bottom and top)

Assignability Rules
Negated types, for perhaps obvious reasons, cannot be related structurally - the only sane way to relate them is in a higher-order fashion. Thus, the rules governing these relations are very important.

A negated type not S is related to a negated type not T if T is related to S.
This follows from the set membership inversion that a negation implies - if normally a type S and a type T would be related if S is a subset of T, when we take the complements of those sets, not S and not T, those sets share an inverse relationship to the originals.
A type S is related to a negated type not T if the intersection of S and T is empty
We want to check if for all values in S, none of those values are also in T (since if they are, S is not in the negation of T). The intersection of S and T, when simplified and evaluated, is exactly the description of the common domain of the two. If this domain is empty (never), then we can conclude that there is no overlap between the two and that S must lie within not T.
A negated type not S is not related to a type T.
A negated type describes a set of values that reaches from unknown to its bound, while a normal type describes values from its bound to never - it's impossible for a negated type to satisfy a normal type

Assignability Addendum for Fresh Object Types
Frequently we want to consider a fresh object type as a singleton type (indeed, some examples in the refs assume this) - it corresponds to one runtime value, not the bounds on a value (meaning, as a type, both its upper and lower bounds are itself). Using this, we can add one more rule that allows fresh literal types to easily satisfy negated object types.

A fresh object type S is related to a negated type not T if S is not related to T.
Since S is a singleton type, we can assume that so long as it's type is not in T, then it is in not T.

Examples
Examples of negated type usage can be found in the tests of this PR (there's a few hundred lines of them, and probably some more to come for good measure), but here's some of the common ones, pulled from the referenced issues:

declare function ignore<T extends not (object & Promise<any>)>(value: T): void;
declare function readFileAsync(): Promise<string>;
declare function readFileSync(): string;
ignore(readFileSync());     // OK
ignore(readFileAsync());    // Should error

declare function map<T, U extends not void>(values: T[], map: (value: T) => U) : U[]; // validate map callback doesn't return void

function foo() {}

map([1, 2, 3], n => n + 1); // OK
map([1, 2, 3], foo);        // Should error

function asValid<T extends not null>(value: T, isValid: (value: T) => boolean) : T | null {
    return isValid(value) ? value : null;
}

declare const x: number;
declare const y: number | null;
asValid(x, n => n >= 0);    // OK
asValid(y, n => n >= 0);    // Should error

function tryAt<T extends not undefined>(values: T[], index: number): T | undefined {
    return values[index];
}

declare const a: number[];
declare const b: (number | undefined)[];
tryAt(a, 0);    // OK
tryAt(b, 0);    // Should error

Fixes #26240.
Allows #27711 to be cleanly fixed with a lib change (example in the tests).
<!-- Should make #28274 possible to fix. --!>

Ref #4183, #4196, #7648, #12215, #18280

Can non-distributive conditional types be simplified?
not (T extends U ? A : B) is T extends U ? not A : not B

So could https://github.com/Microsoft/TypeScript/issues/29941 be solved with this?

You can declare the type not Function, so quite possibly?

I'm super excited for this feature. Many thanks to @weswigham and others for all their work on this!
I have one question around how not types interacts with in as a type guard. Consider this example:
type A = { a: any, f: string } | { b: any, f: number };
declare const a: A;

if ("a" in a) {
  // ...
}

I know that TS currently narrows the type of a to { a: any, f: string } inside the if block, even though this is unsound (because { b: any, f: number } could also have a property "a"). My understanding is that the current behavior is a conscious choice to prefer convenience/intuitiveness over soundness.
My question is: do not types change the calculus around that trade-off? I.e., before it would've been very hard (since exact types aren't supported) for a developer to get the current behavior if TS narrowed in a sound manner. But, with not types, one could write:
type A = { a: any, f: string } | (not { a: any } & { b: any, f: number });

My question is: do not types change the calculus around that trade-off?

I doubt it, considering today you could have already written the union a bit differently to assert that the types couldn't overlap in their type of property a without a negated type being needed:
type A = { a: string | number | symbol | object, f: string } | { a?: undefined, b: any, f: number };

Just a reminder, for people who learned serious type theory, ¬T = T → ⊥ (i.e., not T = (x: T) => never).

Type negation in this context is more like set complement than binary
complement. And types in type theory are more like "if X holds, then Y
holds", not the boolean logic "if X, then Y". For related reasons, material
implication doesn't exist in type logic.

Material implication and function return are two vastly different
things. Please don't confuse the two.

If you haven't already, please feel free to take a look at this:
https://en.wikipedia.org/wiki/Type_theory. It should help cover the basics,
and if you don't know type theory very well, it makes for a pretty nice
primer on the subject.
On Wed, Mar 13, 2019 at 06:59 Belleve Invis notifications@github.com
wrote:

Just a reminder, for people who learned serious type theory, ¬T = T → ⊥
(i.e., not T = (x: T) => never).
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/pull/29317#issuecomment-472375516,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AERrBG5fD_1YujMegBxxtTNVBz7QUhRmks5vWNoNgaJpZM4Z2mt0
.

Material implication and function return are two vastly different things
Actually there is something called “Curry-Howard correspondence”, which builds a connection between logical propositions and programming types.

发件人: Isiah Meadows notifications@github.com
发送时间: Wednesday, March 13, 2019 8:08:50 PM
收件人: Microsoft/TypeScript
抄送: Renzhi Li; Comment
主题: Re: [Microsoft/TypeScript] Negated types (#29317)

Type negation in this context is more like set complement than binary
complement. And types in type theory are more like "if X holds, then Y
holds", not the boolean logic "if X, then Y". For related reasons, material
implication doesn't exist in type logic.

Material implication and function return are two vastly different
things. Please don't confuse the two.

If you haven't already, please feel free to take a look at this:
https://en.wikipedia.org/wiki/Type_theory. It should help cover the basics,
and if you don't know type theory very well, it makes for a pretty nice
primer on the subject.
On Wed, Mar 13, 2019 at 06:59 Belleve Invis notifications@github.com
wrote:

Just a reminder, for people who learned serious type theory, ¬T = T → ⊥
(i.e., not T = (x: T) => never).
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/pull/29317#issuecomment-472375516,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AERrBG5fD_1YujMegBxxtTNVBz7QUhRmks5vWNoNgaJpZM4Z2mt0
.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FMicrosoft%2FTypeScript%2Fpull%2F29317%23issuecomment-472395689&data=02|01|Renzhi.Li%40microsoft.com|3ea031432e1f440c420b08d6a7aca7e7|72f988bf86f141af91ab2d7cd011db47|1|0|636880757331226313&sdata=WihaSOK2tJiCi36Njw9G26IS154PN%2B4FNfLoPwc4M8A%3D&reserved=0, or mute the threadhttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAAOp2xNxWKafDomtKR6FWxjJhKSok49Hks5vWOpSgaJpZM4Z2mt0&data=02|01|Renzhi.Li%40microsoft.com|3ea031432e1f440c420b08d6a7aca7e7|72f988bf86f141af91ab2d7cd011db47|1|0|636880757331226313&sdata=Bf2phXXi70vMC%2BSKkCY4%2FsbwuWgNSUVxVIq5fDCRMmw%3D&reserved=0.

Fair. But as mentioned before, this bug is looking for set complement, not
boolean complement. So that won't work for the purposes we need.
On Thu, Mar 14, 2019 at 11:14 Belleve Invis notifications@github.com
wrote:

Material implication and function return are two vastly different things
Actually there is something called “Curry-Howard correspondence”, which
builds a connection between logical propositions and programming types.

发件人: Isiah Meadows notifications@github.com
发送时间: Wednesday, March 13, 2019 8:08:50 PM
收件人: Microsoft/TypeScript
抄送: Renzhi Li; Comment
主题: Re: [Microsoft/TypeScript] Negated types (#29317)

Type negation in this context is more like set complement than binary
complement. And types in type theory are more like "if X holds, then Y
holds", not the boolean logic "if X, then Y". For related reasons,
material
implication doesn't exist in type logic.

Material implication and function return are two vastly different
things. Please don't confuse the two.

If you haven't already, please feel free to take a look at this:
https://en.wikipedia.org/wiki/Type_theory. It should help cover the
basics,
and if you don't know type theory very well, it makes for a pretty nice
primer on the subject.
On Wed, Mar 13, 2019 at 06:59 Belleve Invis notifications@github.com
wrote:

Just a reminder, for people who learned serious type theory, ¬T = T → ⊥
(i.e., not T = (x: T) => never).
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<
https://github.com/Microsoft/TypeScript/pull/29317#issuecomment-472375516>,

or mute the thread
<
https://github.com/notifications/unsubscribe-auth/AERrBG5fD_1YujMegBxxtTNVBz7QUhRmks5vWNoNgaJpZM4Z2mt0>

.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub<
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FMicrosoft%2FTypeScript%2Fpull%2F29317%23issuecomment-472395689&data=02|01|Renzhi.Li%40microsoft.com|3ea031432e1f440c420b08d6a7aca7e7|72f988bf86f141af91ab2d7cd011db47|1|0|636880757331226313&sdata=WihaSOK2tJiCi36Njw9G26IS154PN%2B4FNfLoPwc4M8A%3D&reserved=0>,
or mute the thread<
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAAOp2xNxWKafDomtKR6FWxjJhKSok49Hks5vWOpSgaJpZM4Z2mt0&data=02|01|Renzhi.Li%40microsoft.com|3ea031432e1f440c420b08d6a7aca7e7|72f988bf86f141af91ab2d7cd011db47|1|0|636880757331226313&sdata=Bf2phXXi70vMC%2BSKkCY4%2FsbwuWgNSUVxVIq5fDCRMmw%3D&reserved=0>.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/pull/29317#issuecomment-472911159,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AERrBBrnFfm39Ns8RROEXS3zqlKiBF40ks5vWmdGgaJpZM4Z2mt0
.

Does this feature mean that type subtraction is now possible?
type A = { x: string; y: string }
type B = { x: string }

type C = A & (not B)     // type C = { y: string }

If so then does subtraction followed by intersection get you back to where you started?
type A = { x: string; y: string }
type B = { x: string }

type C = A & (not B)

type D = C & B         // type D = A

An intersection with a negated type is "stronger" than the subtraction example you give (which the Omit conditional you'll find floating around can already do). An intersection with a negated type means that something which is assignable to the intersection can never be assignable to the negated type. In your example, D and C are both never. A & not B represents all A which aren't B. A is a subtype of B though, so all possible A must be assignable to B. Thus, the intersection is the empty set - never.

@Richiban You mean type D = C | B? One would expect A & (not B) & B to be A & never → never, but A & (not B) | B conceptually removes B and then re-adds it. I didn't write this patch, so this is by no means authoritative, but that's what I'd expect the semantics for negated types to be. And yes, it would provide a relative complement if you're looking at it in terms of set theory.

@isiahmeadows

One would expect A & (not B) & B to be A & never → never

You're right; this is a logical inconsistency that says to me that type subtraction is not expressed as A & (not B).
Given that, can someone point out to me where I'm going wrong with this line of reasoning?
type A = { x: string, y: string }

type B = { x: string }

const var1 : A = { x: "1", y: "2" }

// If `& (not B)` has the effect of removing the members of `B`, then this holds
const var2 : A & (not B) = { y: "3" }

// Intersecting the above with `B` should _add_ the members of `B` back again. But then the type expression contains `B & (not B)` which is `never`
const var3 : A & (not B) & B = var1

@Richiban neither of your last 2 steps are right, I think:

A & (not B) is not { y: string }, it’s never, because B is a supertype of A, so excluding B excludes A and then some
adding & B to a type does not “add back in” the properties of B, it says that it is the preceding type, as well as B, which is an important distinction. If you say that a type doesn’t have a property and then you say it does you haven’t added it back in, you’ve just contradicted yourself. | is the only way to get back possibilities you’ve previously ruled out

@pelotom

A & (not B) is not { y: string }, it’s never, because B is a supertype of A

Thanks for your explanation Tom! This sentence gave me the pointer I needed to find where I was going wrong. It took me an embarrassingly long time to figure out why the example number & (not 0) was so intuitive but my {x: string; y: string} & (not { x: string }) didn't work... I was getting the sub/supertype direction the wrong way round. That's why we end up with no possible values and type never.
I see now that, in logical language, what I want to express (for subtraction) is not

A and not B

but

A but not B

where A is assignable to B.
Thanks for your help everyone.

@Richiban Just thought I'd reiterate type "subtraction" is intuitively a relative complement. And in this case, A & not B translates to "the set of all x in A that are not in B", which is the very definition of "relative complement" (what type subtraction is based on).
I'm not sure what you mean by logical "subtraction" if not that, because to me, "but" as a conjunction implies "and", just with extra contextual implications they're being somehow contrasted.

@isiahmeadows I guess my set theory has failed me in this case... I've reduced what I would like to be able to do to the simplest possible case:
Given that:
D & R = P

Is it possible to rearrange this with D on the left?
D = ????

@Richiban That would be the union of all sets that are a superset or equal to P & (not R) and a subset or equal to P, or in math notation, ∪ {S | S ⊇ P \ R, S ⊆ P}. There's not one specific concrete type for that. This suggestion by me + negated types would be enough for your use case: P & not R | P & super (P & not R).

There is no way to reconstruct D because intersection is a destructive operation. Here is a basic example:
type D = 1 | 2;
type R = 2 | 3;
type P = D & R; // 2

There is no way to get back the 1 in D from the types R = 2 | 3, and P = 2.

if type NotStringLiteral = ...  is expressible, it could help catch typos in code where an object can take both static and dynamically-known properties: https://stackoverflow.com/questions/55725583/is-there-a-way-to-catch-typos-in-string-literals-in-typescript?noredirect=1#comment98130487_55725583.

Will it be possible to do string & not "something" to define all strings that are not "something"?

Am I right, that this would then typecheck?
interface MyRecord {
    foo: number;
    bar: number:
    [s in (string & not ("foo" | "bar"))]: string;
}

(this is basically the same question as @ExE-Boss )

I think we should cross-reference this to #26797, especially in comments that mention the "arbitrary index signature PR", since it seems like we'd need that plus this to support the "default property" requests:
type DefaultProperty<T extends object, V> = T & {[k: (keyof any) & not (keyof T)]: V};

This was removed from roadmap, does that mean it’s not happening?

It's not happening in 3.5, and I think it'll be clearer as to whether we're going to prioritize them in a future version. Right now, I have a few concerns:

Use-cases: { foo: number } isn't assignable to not { bar: string }, so is this feature actually for anyone?
Consistency: can this compose with other features to give expected results? Do you get unknown when mixing and matching the right negated types?
Complexity: can we reason about the implementation long-term?

Phew!
I was afraid to see this accepted as is.

Use-cases: { foo: number } isn't assignable to not { bar: string }, so is this feature actually for anyone?

You need closed types for this to be broadly useful, and you can implement closed types using negations (with indexes). Eg, type Closed<T> = {[index: keyof any & not keyof T]: never} & T, which'd ideally allow Closed<{ foo: number }> to be assignable to not { bar: string } We already consider fresh object literals "closed", you just can't make an always-closed type in the type syntax today. This concern's a liiiiiil overblown, IMO - many of the examples "make this assumption", but the source side is always an object literal so it checks out.

Consistency: can this compose with other features to give expected results? Do you get unknown when mixing and matching the right negated types?

Gosh I hope so. That's like the thing I think we've got really good here.

Complexity: can we reason about the implementation long-term?

We can delete all code relating to intersections as we add negations if you'd like: negations are actually a more foundational type - an intersection A & B & ... & Z can be represented as not ( not A | not B | ... | not Z ), which means there's actually no algebraic need to have first class intersection types once negations exist. (for optimization and API compat the intersection-specific structures are probably worth keeping, tho)

Regarding what is most fundamental: both NAND and XOR are individually sufficient for defining all of the others.

Some quick observations:

Use-cases: { foo: number } isn't assignable to not { bar: string }, so is this feature actually for anyone?

The linked issues have a number of use cases, but perhaps this feature would be more complete if Closed (definable in terms of closed types) could be added to the standard library as part of this PR.

Consistency: can this compose with other features to give expected results? Do you get unknown when mixing and matching the right negated types?

It seems the semantics are just standard set theory.
Still, simple things combined can sometimes be counter-intuitive, (especially for we with tainted intuitions from using nominally-typed languages):

That not { foo: number } isn't assignable to not { bar: string } was initially surprising for me, but it makes sense when I remind myself that types are not 'closed' by default: {bar: string} is a shorthand for { bar: string } | { bar: string, foo: number} | { bar: string, foo: string, baz: any } | ....

Compared to mapped types and conditional types, this feature is probably equally learnable, though some user testing would be interesting.

Complexity: can we reason about the implementation long-term?

To my uneducated eye, the maintenance burden seems very small: this feature adds < 80 CLOC of code to the checker, none of which pops out as different in spirit or complexity from surrounding code.

We can delete all code relating to intersections as we add negations if you'd like: negations are actually a more foundational type

Ooh, foundational!  😈  We can replace unions, intersections, and negations, with a single operation ⩃!
type Not<A> = A ⩃ A
type Union<A, B> = (A ⩃ A) ⩃ (B ⩃ B)
type Intersection<A, B> = (A ⩃ B) ⩃ (A ⩃ B)
type Unknown = (string ⩃ string) ⩃ string
type Never = ((string ⩃ string) ⩃ string) ⩃ ((string ⩃ string) ⩃ string)

Who's with me?  All in favor, say 👎⩃👎!

Use-cases: { foo: number } isn't assignable to not { bar: string }, so is this feature actually for anyone?

Are there two subpoints to consider here?

Whether users need or want that to hold, and therefore if it doesn't that's a significant limitation.
Will that be a significant impediment to learning because users expect that to hold, and these unsatisfiable constraints get shoved in their face.

On the first point: I'm not sure I see this as a major use case of negated types, so the fact it does not hold is non-issue for me. IMO, the main use of negated types is being able to add negative constraints obtained through first order checks to types that are atomic (and thus cannot be filtered). For instance, being able to say string & not "", or T & not undefined. I'm not sure how much I would really need higher-order negative constraints such as not { bar: string }; the only exception would be with a discrimination union constraint on a generic type:
T extends ({ kind: 1; a: string } | { kind: 2; b: boolean }) & not { kind: 1 }

But I think this should work correctly because { kind: 2; b: boolean } and {kind: 1} are disjoint, right?
On the second point: I don't think it's a significant hurdle. In some ways I think negated types 'tie the knot' on the set-theoretic types in TypeScript, so in conjunction with intersection and union it might help users see the big picture. The reason why { foo: number } not being assignable to not { bar: string } might trip someone up is fundamentally the same reason why people get tripped up on { foo: number } & { bar: string } seemingly "adding" behaviour (and thus being union-like), when it's really set intersection. Both phenomena can be nicely described using a venn-diagram.
I don't think types like not {bar: string } will naturally arise in programs unless users actually write them; that is, they shouldn't be synthesised through narrowing. So hopefully users that might be still getting to grips with the language wont have types like that popping up from nowhere.

When I first heard about this feature I was excited because I thought it would be useful in modelling arrays with at least 2 elements.  My use case is ASTs of math expressions where addition and multiplication are n-ary operations but need at least two operands.  With the proposed not syntax is it possible to model this?  Would it look something like the following?
type ArrayOfTwoOrMore<T> = not [] & not [T] & T[];

@kevinbarabash
type ArrayOfTwoOrMore<T> = [T, T, ...T[]]

I have a use case in real-world dev here. happy to see this get into master. Here is a simplified version of my use case.
function wowWithElement<T>(self: Wow<T>, node: any): self is typeof self extends Wow<infer U> ? Wow<U & Element> : Wow<T> {
    return node instanceof Element
}
// ! I can't write such a type without this PR !
function wowWithoutElement<T>(
     self: Wow<T>,
     node: any
): self is typeof self extends Wow<infer U> ? Wow<U & not Element> : Wow<T> {
//------------------------------------------ or Wow<not Element>, depends on the type compute rule
     return !magic(self, node)
}
class Wow<T> {
    value: T extends Element ? number : string

    action(node: T) {
        const self: Wow<T> = this
        if (wowWithElement(self, node)) {
            // ? this is Wow<T & Element> and node extends Element
            self.value.toExponential(233) // ? number
        }
        if (wowWithoutElement(self, node)) {
            // ? this is not extends Wow<Element> and node does not extend Element
            self.value.split(' ') // ? Should be string here. But I can't write type for wowWithoutElement without this PR
        }
    }
}

I guess this PR is the only way for React users to declare additional props. I mean this:
interface BaseProps {
  prop1: string,
  prop2: number,
}

interface ExtraProps<T> {
  [index: string & not keyof T]: unknown,
}

type FinalProps = BaseProps & ExtraProps<BaseProps>

This allows to add any props to component without breaking type safety, because now if we add index signature to props it disables type check (what's the reason for using TS then?). I hope to see this PR in master!

@777PolarFox777 In general, I would recommend against a component API that allows completely arbitrary extra props, but it can be done like this:
function MyComponent<P extends BaseProps>(props: P) {
  // ...
}

(Feel free to ping me on Twitter if you want to follow up on this outside the scope of negated types.)

@andrewbranch thank you! Your solution is much better than usage of index signature, I'll note this :)

That can be used in JS too like:
/**
 * @template {BaseProps} P
 * @param {P} props
 */
function MyComponent(props) {
	// ...
}

But there is still no solution to something like this:
type Options = {
    foo: number;
    [others: string]: string;
};

@jvanbruegge:
type Options = {
    foo: number
} & {
    [others: string]: string;
};

No that does not work:
type Options = { foo: number; } & { [others: string]: string; };

const x: Options = { foo: 4, bar: "Hello" };

gives the error:
Type '{ foo: number; bar: string; }' is not assignable to type 'Options'.
  Type '{ foo: number; bar: string; }' is not assignable to type '{ [others: string]: string; }'.
    Property 'foo' is incompatible with index signature.
      Type 'number' is not assignable to type 'string'.

@jvanbruegge maybe something like this? 🙈
type Options<T extends object> = {
    [P in keyof T]: P extends 'foo' ? number : string
}
const createOptions = <T extends Options<T>>(o: T) => o;

const x = createOptions({ foo: 4, bar: "Hello" })

You would probably need #26797 to get it right:
type Options = {
    foo: number;
    [string & not "foo"]: string;
};

I would like to see this get into Typescript. I run into the following pattern fairly often that I am unable to type correctly without it (that I know of).
type BasicConfig = { [key: string]: any };

// You can await a sync function
type AsyncFunction = () => Promise<BasicConfig> | BasicConfig;
type SyncFunction = () => BasicConfig;

const syncFn1: SyncFunction = async () => ({ sync: false }) // should error
const syncFn2: SyncFunction = () => ({ sync: true }) // passes as expected

const asyncFn1: AsyncFunction = async () => ({ sync: false }) // passes as expected
const asyncFn2: AsyncFunction = () => ({ sync: true }) // passes as expected

This might have come up before, but just wanting a second pair of eyes to know if I'm understanding how this can be used:
interface Cx<S extends string = string> {
  s: S;
  isS<SS extends S>(s: SS): this is Cx<SS>;
}

const fn = (cx: Cx) => {
  if (cx.isS('hello')) {
    return;
  }
  console.log(cx.s);
};

Am I correct in believing that given the guard, the else branch represents not Cx<"hello">?
(I know that narrowing using not isn't in this PR, but given that's a natural extension, I'm thinking just in general)

[···] the else branch represents not Cx<"hello">
@G-Rath

I didn't try out but I'd say [···] the else branch represents not Cx<string>.

@SalathielGenese I hope not, as that's a wider type than what is being guarded against.

It would likely be Cx<string> & not Cx<"hello"> if negated types were to be used.

I'm wondering if some of the identities proposed here are potentially problematic. In particular
not not T is T
Programming language type systems are usually constructive right?, i.e. they deny the law of excluded middle which is what's being used here. I can't think of a specific example of where this would be an issue but I'm concerned that this may lead to weird soundness issues. I guess not T is usually encoded in programming languages as T => never. So maybe I have the wrong mental model here.
Also are these identities true?
T | not T is unknown
T & not T is never

@DylanRJohnston The operator not proposed here is interpreted using a set-theoretic model rather than a logical model, like most other TypeScript type operators. In this setting types denote sets of values rather than logical propositions. The operator not T is denoted by the set of all values not in the set denoted by T, so unknown \ T.

Intersection and union are interpreted in a set-theoretic way, too. But yeah, the not operator is pretty much set complement and the rules listed are just De Morgan's laws.

I wonder if CFA makes too complex unreadable types (especially for beginners) in the future. And if CFA doesn't affect negated types, negated types are useless for common programming. So I think since balancing conciseness and strictness with negated types is very difficult as above, negated types won't be useful for common programming.

I mean, you could always just hide negated types from the display if visual complexity was the worry - it's technically no different than how a union narrows down in CFA today - just the inversion of it. The issue is just that unlike with a union where you're always removing members, when I'm talking about "removing things via adding negations", I'm building a larger list of intersected things, which has algorithmic implications - namely that graph complexity grows as more narrowing are applied, rather then shrinks.

I wonder if CFA makes too complex unreadable types (especially for beginners) in the future.

What does CFA mean?

@Tyler-Murphy Control Flow Analysis. The thing where typescript narrows types based on previous statements. (if, switch, assignments, type guards, etc)

Control flow analysis.
A type synonym like truthy number which is equivalent of number & not 0 may solve this problem. However, I think truthy is not a good keyword.

How does not interact with function types. e.g. not ((a: A) => B), in particular with the contra and co variance of A and B respectively?

Since signatures combine pretty freely, it's virtually impossible to make a negated type to which one signature is assignable but not another (at least, without having a negated type intersected with that signature to qualify it).
This is because for any signature, you could always intersect both that signature and the signature type within the negation to get something which is a subtype of both, and this intersection would never simplify to the empty set (as for all signatures, an intersection of those signatures is defined to be the overload list of those signatures). So a (x: string) => void wont be assignable to a not (x: number) => void, because a {(x: string): void; (x:number): void;} can be made, which is a member of both.

I think I understand, is it fair to say then that not any type of function is simply not Function? What about (_: not string) => void or () => not string?

It can't actually simplify because you can still append bounds onto your signatures, like SignatureA & not SignatureB, which would effectively forbid any subtype of such a type from providing a match for the negated signature. (This is sorta how fallthru in overload resolution would be modeled as conditionals)

Relevant question: https://github.com/microsoft/TypeScript/pull/33018#issuecomment-524529473

Does there exist any reason against using ! and ~ instead of not for negated types?
I would prefer using !, if possible, because it is a more natural way to express the negative of something in C-like languages like JavaScript and TypeScript: ! && || are used as logical operators, and ~ & | are used as bitwise operators. Furthermore, | is used for union types, and & is used for intersection types.

@weswigham Is there a way we can test this out on the playground/in our projects, I saw there was a special build for https://github.com/microsoft/TypeScript/pull/38305. Could we have the same here to give feedback?

It may need a rebase for that, but we can see
@typescript-bot pack this

Would this enable us to inform consumers of functions that they can't pass an array?
Please excuse the contrived example. But it illustrates the signature I'm looking to write.
function getObjectKeys<T extends object not Array<unknown>>(input: T) {
  return Object.keys(input);
}

Because the current need to have to throw at runtime feels like it's against TypeScript's goals of catching bugs at runtime. i.e.
function getObjectKeys<T extends object not Array<unknown>>(input: T) {
  if(Array.isArray(input)){
    throw new Error('expected an object, not an array')
  }
  return Object.keys(input);
}

If this change does not plan to solve this use case, please let me know and I can make a new issue.

@dgreene1
function getObjectKeys<T extends object & not Array<unknown>>(input: T) {
  return Object.keys(input);
}

You forgot an &, but that's how you'd do it.

I guess the not construct is maybe clearer but there are options today, like function foo<T extends {[k: string]: any, [n: number]: never}>(arg: T).  Of course not every object with number keys is an Array, but it will flag any Array passed at runtime unless it's an empty literal (or you explicitly type it as Array<never>).

@dgreene1
You might want to do not ReadonlyArray<unknown>, since that covers both read‑only arrays and read‑write arrays.

I guess the not construct is maybe clearer but there are options today, like function foo<T extends {[k: string]: any, [n: number]: never}>(arg: T). Of course not every object with number keys is an Array, but it will flag any Array passed at runtime unless it's an empty literal (or you explicitly type it as Array).

I appreciate the suggestion, but that solution does not work for all cases. In fact, it might be a little dangerous because it requires the input type to have an iterable index which might lead developers to add an index signature to their interfaces once they see this error:
Argument of type 'ITestCase' is not assignable to parameter of type 'ObjectNotArray'.   Index signature is missing in type 'ITestCase'.ts(2345)
So ultimately I think I'll stick to the runtime check until this PR is approved. Thank you @weswigham for creating this PR and thank you @isiahmeadows / @ExE-Boss for confirming the not solution. @DanielRosenwasser, I believe that my scenario above clarifies the value of this PR. Have I mentioned how much I love the Typescript community? :) Cause I do. ❤

I would really love to try this out with TypeScript 4.1 but the conflicts are massive and unmanagable to resolve if you don't know a lot about the internals. Would you be willing to rebase @weswigham? I know this is a lot to ask for.

A thought on identity rules.
I think these should be the proper identities
1 not not T is T
2 not (A | B | C | ...) is not A & not B & not C & not ...
3 not (A & B & C & ...) is not A | not B | not C | not ...
4 not any is never
5 not never is any
6 not unknown is either unknown or illegal keyword combination.
Explanation

not any is never

we know that any is union of all types or any is (string | bool | number | object | function | null | undefined)

Then not any is not string & not bool & not number & not object & not function & not null & not undefined [ From identity that not (A | B | C | ...) is not A & not B & not C & not ...]

It means that not any cannot be anything. So its better to say not any is never

not never is any

not never == not never
not never == not (not any) [ From updated identity of not any is never]
not never == any [ From identity that not not T is T]

Exploring case of not unknown

not unknown is unknown

If we do not know the type of x, then how can we know the type of not x
Suppose we have a set TypeSet == { A, B, C }. Now say x belongs to one of the type from TypeSet, but is not clearly know. So we can say that x is unknown.
If x is A, then not x is { B, C }
If x is B, then not x is { A, C }
If x is C, then not x is { A, B }
So by this we can say that if x is unknown then not x is also unknown.

not unknown is illegal keyword combination.
By linguistic design not unknown should be known. But it does mean anything, as there is no type meaning known. If I assign id : not unknown, it doesn't mean that its automatically going to derive to string or number depending upon my use case. So not unknown can be invalid syntax in type system.

@AmitDigga I would've thought that since unknown represented the top type (all values are assignable to it), not unknown would evaluate to never (as no values are assignable to it).

this will not become a problem, right?

not any = never
not unknown = never
not any = not unknown
any = unknown

@dimitropoulos
10=0 and 20=0 doesn't make 1=2, maybe this relation also applies to the not operator

right, totally get that.  that's why I was asking (to just make sure) that we think we will not run into an issue with identity related to how not any and not unknown evaluate.

Its little confusing to me, but let me explain my point
We are dealing with set theory. So, lets say if our universal set U is {bool, string, number, object, function, undefined, null, void}

By our definition of any we know that any = U = {bool, string, number, object, function, undefined, null, void}
never is empty set = {}
unknown is some subset from U say Unknown.

Expansion

not function is
= U - function
= {bool, string, number, object, undefined, null, void}

not any is
= U - any
= U - U
= {}
= never

not never is
= U - {}
= U
= any

not Unknown is
= U - Unknown
= a subset from U, which is still not known
= unknown

@isiahmeadows Can you clear confusion over here. I sill think that any is universal set, and unknown is some subset of universal set, which is not known yet.
@dimitropoulos
Either not any == never is going to be true or not unknown == never is going to true. Both cannot be true since any is not equal to unknown
@Jack-Works dividing by 0 analogy wont work over here as dividing by zero gives undefined. In set theory, not of something is clearly defined.
If not X == not Y, it only means that X == Y.

Its little confusing to me, but let me explain my point
We are dealing with set theory. So, lets say if our universal set U is {bool, string, number, object, function, undefined, null, void}

By our definition of any we know that any = U = {bool, string, number, object, function, undefined, null, void}
never is empty set = {}
unknown is some subset from U say Unknown.

...
I sill think that any is universal set, and unknown is some subset of universal set, which is not known yet.

If you're thinking of types as sets where "T ⊆ U" encodes "T is assignable to U" then:

never is the empty set
unknown is the universe
any is a lawless monster (behaves as both never and unknown depending on its mood)

In terms of assignability:

never:

nothing is assignable to never except never (the empty set has no subset)
something of type never is assignable to anything (the empty set is a subset of every set)

unknown:
- anything is assignable to unknown. (all sets are subsets of the universe)
- unknown is not assignable to anything except unknown (the universe is not a subset of anything except universe)

I'm using "universe" here to refer to the set which has all other sets as subsets (top)–which exists in our case

Re "unknown is some subset of universal set, which is not known yet."
The naming of "unknown" here can cause confusion, as it sounds somehow more epistemic than the other types. It's not. In latticey speak, 'unknown' is top and 'never' is bottom, that's it.
To pump the intuition about knowledge a bit: the more general a type is, the more things can inhabit the type. So the more general a type is, the less we know about it, until (in the extreme case) we know nothing at all: that's what unknown is. For example, if something is a string | number we know a lot less about it than if we know it is a string.

note: this ordered set metaphor is imperfect

@AmitDigga

@isiahmeadows Can you clear confusion over here. I sill think that any is universal set, and unknown is some subset of universal set, which is not known yet.

unknown is the universal set. As TS doesn't assume its primitive types cover all values, you can't narrow unknown to a single primitive type except by explicitly checking for that primitive type. But this is still generally consistent with the fact unknown represents the universe of TS types.
any is a near full opt out of the type checker, as more or less a "trust me, this is true, even if it looks inconsistent". The only thing any is not assignable to is never, but literally everything, including any, is assignable to any. But since no set can both be a subset and a superset of disjoint sets, any doesn't represent a set at all, much less a universal set.

Here's how those two narrows in practice, if it helps: Playground Link

It would amazing to have this functionality! Should we expect this PR to be included in some minor release of Typescript 4? Or is that too far fetched?

Hmm, so the root feature, as described in this PR isn't too contentious (there's some hesitation because the concept may be too complex), but the driver for implementing the feature, using them in control flow to more precisely narrow negative branches on generics, last time I checked (in a different branch based on this PR) had bad performance implications that I couldn't easily work around. Other changes, like caching relationship results on intersection comparisons (we have an open pr for that), or better alias finding (and that) might improve that performance profile.

I think I've been following this PR in hopes that negated-types gives me an easy way to express index signatures with exceptions, e.g.
class Foo {
  bar(): boolean;
  baz(): number;
  [k: string & not ("bar" | "baz")]: string;
}

const f = new Foo();
foo.bar(); // boolean
foo.catz; // string

If I'm remembering how I got here correctly, just as a data point, there are a lot more people like me waiting for a simple solution to "indexable classes" (without using intersection types).

@thw0rted you can do it today using a hack:
class Foo {
    // @ts-ignore
    bar(): void {}
    // @ts-ignore
    baz(): boolean { return true }
    [k: string]: string;
}

const f = new Foo();
f.bar(); // void
f.catz; // string
f.baz(); // boolean

@Jack-Works that's a more palatable way of keeping a broken declaration inside one class, but it's still broken for interfaces:
interface Oops {
  [k: string]: string;
  // @ts-ignore
  bar: number;
  // @ts-ignore
  baz: boolean;
}

// "Property 'bar' is incompatible with index signature."
const o: Oops = {
  bar: 1,
  baz: true,
  catz: "hey"
};

I haven't had a chance to try this branch yet but I think it would solve both cases, without any messy ts-ignores.

@thw0rted please checkout #41524

Is it possible to use something like to express a lack of keys in a record? For example if we might want to describe an operation that "cons"-es records, i.e. inserts a key value pair into a record that does not already contain the corresponding key. :
type KeyLike = string | number | symbol

type HasKey<K extends KeyLike> = { [key in K]: unknown }
type LacksKey<K extends KeyLike> = not HasKey<K>

type Merge<O1, O2> = {
    [k in (keyof O1 | keyof O2)]:
      O2 extends HasKey<k> ? O2[k]
    : O1 extends HasKey<k> ? O1[k]
    : never
}

declare const consRecord: <K extends string, V, O extends LacksKey<K>>(k: K, v: V, o: O) => Merge<{ [key in K]: V }, O>

Is it possible to use something like to express a lack of keys in a record? For example if we might want to describe an operation that "cons"-es records, i.e. inserts a key value pair into a record that does not already contain the corresponding key. :
type KeyLike = string | number | symbol

type HasKey<K extends KeyLike> = { [key in K]: unknown }
type LacksKey<K extends KeyLike> = not HasKey<K>

type Merge<O1, O2> = {
    [k in (keyof O1 | keyof O2)]:
      O2 extends HasKey<k> ? O2[k]
    : O1 extends HasKey<k> ? O1[k]
    : never
}

declare const consRecord: <K extends string, V, O extends LacksKey<K>>(k: K, v: V, o: O) => Merge<{ [key in K]: V }, O>

Happy one-year anniversary of the negated types PR, everyone 🎉
Some nice reading to celebrate: https://pnwamk.github.io/docs/dissertation.pdf

Happy one-year anniversary of the negated types PR, everyone 🎉
Some nice reading to celebrate: https://pnwamk.github.io/docs/dissertation.pdf

Happy one-year anniversary of the negated types PR, everyone 🎉

2-year anniversary, to be precise.

Happy one-year anniversary of the negated types PR, everyone 🎉

2-year anniversary, to be precise.

Any update on this? Just ran into this problem today while trying to create a simple standalone utility function that would serve as a type predicate to sort on the question, "Does the specified property name of object both exist on object and contain a truthy value?" and found myself at an impasse because, although both are possible, I couldn't figure out a way to express this as a predicate return type without being able to filter on Exclude<unknown,undefined|null|false|0|0n|""> and get a narrowed type in the generic case when knowable.

This fits really well with the template literal type feature in #43376 and index key types in #26797 also. Would be useful in https://github.com/microsoft/vscode which uses square bracketed keys for scoped configuration like so:
{
  "workbench.colorCustomizations": {
    "[Github Sharp]": {
      "activityBarBadge.background": "#0366d6",
      "statusBarItem.remoteBackground": "#0366d6"
   }
   "gitDecoration.untrackedResourceForeground": "#91B859"
  }
}

Keys can be either a "[key]": object or a "key": string, and typing that would be real useful in the IDE.

This fits really well with the template literal type feature in #43376 and index key types in #26797 also. Would be useful in microsoft/vscode which uses square bracketed keys for scoped configuration like so:
{
  "workbench.colorCustomizations": {
    "[Github Sharp]": {
      "activityBarBadge.background": "#0366d6",
      "statusBarItem.remoteBackground": "#0366d6"
   }
   "gitDecoration.untrackedResourceForeground": "#91B859"
  }
}

Keys can be either a "[key]": object or a "key": string, and typing that would be real useful in the IDE.

Mithril actually needs this to differentiate onevent from string attributes - it's a blocker for us migrating to delegate to the DOM's official types.

By the way, for those who want to use negated types in function parameters, you can already (at least in v4.3.5) mimic it by using conditional types for the parameter's type:
function f<T>(x: T extends string ? never : T) { return x }

f(42)
f("42") // Argument of type 'string' is not assignable to parameter of type 'never'.(2345)

TS Playground

@yuhr

By the way, for those who want to use negated types in function parameters, you can already (at least in v4.3.5) mimic it by using conditional types for the parameter's type:
function f<T>(x: T extends string ? never : T) { return x }

f(42)
f("42") // Argument of type 'string' is not assignable to parameter of type 'never'.(2345)

You can also use pseudo enums to get readable error messages:
declare enum non_string { non_string = '' }

function f<T>(x: T extends string ? non_string : T) { return x }

f(42)
f("42") // Argument of type '"42"' is not assignable to parameter of type 'non_string'.(2345)

But the approach you have suggested has significant drawbacks. The most serious of them is that you can't combine such functions with others. You can't pass it as an argument to other functions, because the type inference will be broken, you can't apply Parameters and ReturnType types to them e.t.c. It's the flaw of the TypeScript itself, that some parts of the language contradict others. Therefore, there is nothing we can do about it, except to abandon the use of this approach.

There's also the inability to use the conditional type without a Anders type parameter (e.g. f<42>(42))

There's also the inability to use the conditional type without a Anders type parameter (e.g. f<42>(42))

Any update on negated types ?

Would love to have type 'string & not ""' and 'number & not 0'

Would love to have type 'string & not ""' and 'number & not 0'

If you haven’t seen it already: https://github.com/microsoft/TypeScript/pull/29317

This has been something I've really been wanting again today to be able to define a factory or type function that is arbitrarily generic.
Effectively I'm currently doing the following:
type Create<Ctx, T> = (ctx: Ctx) => T;
type Liftable<Ctx, T> = T | Create<Ctx, T>;

function lift<Ctx, T>(
    ctx: Ctx,
    liftable: Liftable<Ctx, T>,
): Create<Ctx, T> {
    if (typeof liftable === "function") {
        return liftable;
    }
    return () => liftable;
}

But predictably return liftable is the error:
Type 'Create<Ctx, T> | (T & Function)' is not assignable to type 'Create<Ctx, T>'.
  Type 'T & Function' is not assignable to type 'Create<Ctx, T>'.
    Type 'Function' provides no match for the signature '(ctx: Ctx): T'.(2322)

This obviously happens because typeof liftable === "function" couldn't distinguish if T itself was a function type. So the usual hack is just to do:
return liftable as any;

However for my purposes there's actually no use cases where Liftable<Function> needs to be allowed, it would be far preferable to define everything as:
type Create<Ctx, T extends not Function> = (ctx: Ctx) => T;
type Liftable<Ctx, T extends not Function> = T | Create<Ctx, T>;

function lift<Ctx, T extends not Function>(
    ctx: Ctx,
    liftable: Liftable<Ctx, T>,
): Create<Ctx, T> {
    if (typeof liftable === "function") {
        return liftable; // Hey this is type safe now
    }
    return () => liftable;
}

@Jamesernator You likely got struck by https://github.com/microsoft/TypeScript/issues/37802, not this.

This is also something I'd like to see, due to an unfiled duplicate of #48373 where it's noted

You can't represent a type "any string except this one" in TypeScript.

Sometimes it would be quite useful to be able to do that; for example when using the 'kind' attribute of a library type (e.g. FileSystemHandle in the DOM) to discriminate between subclasses and wishing to include a general else clause reporting an unrecognized kind in case additional subclasses are added in the future.

Love coming back to this PR about once or twice a year because of not being able to do something.
Is there a chance to get any update on the state of it?

Would support for negated types make type inference involving conditional types easier and/or more powerful?

This experiment is pretty old, so I'm going to close it to reduce the number of open PRs.

@sandersn Is that a "no" to negated types, or will the concept be tracked somewhere else now? If the latter, I'd like to know where so that I can subscribe to the new conversation.

Not "no", but discussion should happen on an issue, #4196 probably, instead of a PR. PRs go stale.

(Though the proposal in the PR description is admittedly way more concrete and detailed than anything in that issue rn, and the blockers for this are less about the syntax and behavior and more about implementation and performance + language complexity concerns, all of which are more tied to this PR specifically than the original idea)

while I certainly can relate to wanting to keep the PR count down to a manageable number (we have the same problem over on insomnia), I would like to echo the above from @weswigham.  I've been following this conversation very closely for years, since it and #29729 are the two features I am the most interested in.
I guess at the end of the day as long as this PR isn't locked we can all keep talking here, but it'd be fantastic to have a better understanding of what needs to happen next for negated types to rise-the-ranks a little in the prioritization.  I don't want to spam iteration plans (e.g. https://github.com/microsoft/TypeScript/issues/49074) with my wants-and-needs... but I'm not sure what else to do at this point.
I hit the need for negated types on a weekly basis.  Should I just drop those use-cases in here whenever I hit them?

Thanks for mentioning https://github.com/microsoft/TypeScript/issues/49220. I didn't even know I had this problem till I read it. What I'm hearing is that I should follow future discussion of negated types in https://github.com/microsoft/TypeScript/issues/4196? They'd be absolutely wonderful to have for stuff like "number without NaN".

Why was such a basic and important feature rejected for a type system? That's a pity!

@Autumn-one It wasn't rejected, the issue is still open: #4196
As to why it's not implemented yet? Priorities, time constraints, language constraints, limited resources. Feel free to fork the TypeScript repo and try to implement it, you'll see that it's not an easy task.

authors: 4086606 777PolarFox777 AmitDigga Autumn-one DanielRosenwasser DylanRJohnston ExE-Boss G-Rath Jack-Works Jamesernator JustFly1984 MartinJohns PetaSoft Richiban SalathielGenese Tyler-Murphy acutmore ajafff andrewbranch awerlogus be5invis chrisblossom coalpha dead-claudia dgreene1 dimitropoulos dragomirtitian ethanresnick falsandtru felixfbecker isiahmeadows jack-williams jamiebuilds jcalz jsejcksn jvanbruegge karol-majewski kevinbarabash lgenzelis markusjohnsson masaeedu mheiber mohe2015 mscottnelson orta ostrebler pelotom piecyk qwelias sandersn strelga thw0rted wbt weswigham yuhr


text:
Make triple-slash comment classification more restrictive

It was overly permissive and ended up making a mess of C#-style comments:
/// <summary>Text</summary>
Now it checks the element name.  Attribute names remain unchecked.

@typescript-bot cherry-pick this to release-3.6

@RyanCavanaugh I believe these are the relevant errors:
Deprecation: [@octokit/rest] octokit.authenticate() is deprecated. Use "auth" constructor option instead.

Deprecation: [@octokit/rest] "number" parameter is deprecated for ".issues.createComment()". Use "issue_number" instead

source: gharchive/pull-request

repo: microsoft/TypeScript

license_type: permissive

license_source: github-api


text:
importsNotUsedAsValue affects semantic diagnostics

Fixes #36000
@amcasey or @sheetalkamat for review
Does this need a test and if so, how to test this properly?

@ajaff Test can be added similar to https://github.com/microsoft/TypeScript/blob/master/src/testRunner/unittests/tscWatch/programUpdates.ts#L1089

authors: ajafff sheetalkamat


text:
Fix creation of composite union type predicates

Fixes #54143.

@typescript-bot test this
@typescript-bot user test this inline
@typescript-bot run dt
@typescript-bot perf test faster
@typescript-bot test top100

The new error in the vscode project is precisely an example of relying on the issue we're fixing: A union of two function types where one is a type predicate and the other is just a boolean returning function. It definitely isn't sound to rely on the boolean function proving or disproving anything, so the new error is correct.

@typescript-bot cherry-pick this to release-5.1

authors: DanielRosenwasser ahejlsberg


text:
Fix issue with optional chaining and type inference in type guard

Fixes #34974

@typescript-bot test top100
@typescript-bot user test this
@typescript-bot run dt
@typescript-bot perf test this

It must be getting too close to spooky season because I read the issue title as "Fix issue with ... type gourd" 🎃

authors: Zzzen fatcerberus jakebailey


text:
make building UVAtlasTool optional in cmake

This PR makes building UVAtlasTool optional in CMake, and it's defaulted to on. If we want to turn it off, we can do cmake -DBUILD_TOOLS=OFF .. while configuring CMake.

Nice. Learning a lot about Cmake today :)

@walbourn Can you make a release? Even if it's just a minor release it will be helpful. I am going to coordinate with vcpkg to compile UVAtlas on Windows, they manage packages on a release basis and the main language they operate on is CMake.

I'll do another release of all my libraries by the end of the week.

Actually let's not do the release just yet, we still need to add the export and install in CMakeLists to make it fully functional but it requires compilation. Let me find a Windows machine to add it.

authors: jasjuang walbourn

repo: microsoft/UVAtlas

license: MIT


text:
vi / vim editor on WSL2 hangs when opening any file

Env
Microsoft Windows [Version 10.0.18362.1082]
wsl2: Ubuntu-20.04
Problem
vi just hangs. same as vim --clean
kill pid or Ctrl+C can continue open vi but cannot read any content of the file.
Strace of the command
https://gist.github.com/firealone147/a22d5c092f1c49540ad4ee128c46196c

check echo $DISPLAY  and try unset DISPLAY before run vi ?

Thanks for the strace(1) log output (always appreciated).
connect(3, {sa_family=AF_INET, sin_port=htons(6000), sin_addr=inet_addr("192.168.134.193")}, 16

That IP address doesn't look like a Windows host. On WSL2 they end in .1.

Since you mentioned $DISPLAY, I just find out the problem is X11 fowarding setting.
If I close X11 forwarding daemon on Windows, this will happen.
It behaves normally if I open the daemon on Windows.
Thanks for the help.

source: gharchive/issue

repo: microsoft/WSL


text:
NameChanger - Update INF Errors during Build.

Building the NameChanger project showed following errors:

"[DefaultInstall]-based INF cannot be processed as Primitive"

Made changes as mentioned in the link: https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/creating-a-primitive-driver
There are other drivers which show the same issue. If this is merged, will make changes for others as well.

Adding code changes for adding functions to the Text Allocation using Pragmas.

repo: microsoft/Windows-driver-samples

license: MS-PL


text:
Troubleshooting with ChatGPT-4

It seems there's a bit of confusion. Let's clarify:
Docker Command Inside Docker: You tried to run a docker command inside the Docker container. This won't work because the Docker CLI isn't installed inside the container. You should run Docker commands from your host machine's terminal, not inside the container.
Using pyautogen in Python: When you tried to use pyautogen in the Python shell, you received a NameError. This is because you need to import the library before you can use it.
Let's try using pyautogen correctly:
Start the Python interactive shell inside your Docker container (you've already done this).
Import the necessary components or the entire library from pyautogen. For example:
python
Copy code
from pyautogen import [specific_component]
or
python
Copy code
import pyautogen
Now you can use the functions and classes provided by the pyautogen library.
If you're unsure about how to use pyautogen, refer to its documentation or provide me with a specific task you want to achieve, and I can guide you through it.
User
root@f1e846ae5f73:~# import pyautogen
import-im6.q16: unable to open X server `' @ error/import.c/ImportImageCommand/346.
ChatGPT
The error you're seeing (import-im6.q16: unable to open X server) is not related to Python's import statement. Instead, it's related to the import command from ImageMagick, a suite of command-line tools for image manipulation. This error can occur when you're running commands in a terminal without an X server (a graphical server) available.
To resolve this, you should be inside the Python interpreter when trying to import Python modules. Here's how you can do it:
Start the Python interpreter by typing python or python3.
Once inside the Python interpreter, you can then use the import statement to import the pyautogen module or any other Python module.
bash
Copy code
root@f1e846ae5f73:~# python
Python 3.10.13 (main, Sep 20 2023, 11:11:20) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

import pyautogen
This should work without any issues. If you still encounter problems, let me know, and we can troubleshoot further.

User
root@f1e846ae5f73:~# python
Python 3.10.13 (main, Sep 20 2023, 11:11:20) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

import pyautogen
Traceback (most recent call last):
File "", line 1, in
ModuleNotFoundError: No module named 'pyautogen'
ChatGPT
It seems that the pyautogen module is not available in the Python environment you're currently using, even though pip indicated that it was installed.

Let's try a few things to troubleshoot:
Check the Python Path: Sometimes, the Python interpreter you're using might not be the one where the module was installed. Let's check where pip installed the module.
python
Copy code
import sys
print(sys.path)
This will print out the paths where Python looks for modules. Ensure that the site-packages directory where pip installs packages is listed.
Check Installation with pip: Use pip to list installed packages and see if pyautogen is among them.
bash
Copy code
pip list | grep pyautogen
This should show pyautogen and its version if it's installed.
Reinstall the Module: Sometimes, reinstalling can help. You can uninstall and then install the module again.
bash
Copy code
pip uninstall pyautogen
pip install pyautogen
After reinstalling, try importing it again in the Python interpreter.
Use Python's -m Flag: Sometimes, you can run a module using Python's -m flag, even if you can't import it in the interpreter. Try:
bash
Copy code
python -m pyautogen
If the module provides a command-line interface or a main function, this might run it.
If none of these steps resolve the issue, there might be a deeper problem with the Python environment or the way the Docker container is set up. Let me know the results, and we can proceed from there.
User

import pyautogen
Traceback (most recent call last):
File "", line 1, in
ModuleNotFoundError: No module named 'pyautogen'
import sys
print(sys.path)
['', '/usr/local/lib/python310.zip', '/usr/local/lib/python3.10', '/usr/local/lib/python3.10/lib-dynload', '/usr/local/lib/python3.10/site-packages']
pip list | grep pyautogen
File "", line 1
pip list | grep pyautogen
^^^^
SyntaxError: invalid syntax
pip uninstall pyautogen
File "", line 1
pip uninstall pyautogen
^^^^^^^^^
SyntaxError: invalid syntax
pip install pyautogen
File "", line 1
pip install pyautogen
^^^^^^^
SyntaxError: invalid syntax

ChatGPT
It seems you're trying to run shell commands directly within the Python interpreter, which is causing the syntax errors.
Let's exit the Python interpreter and then run the shell commands:
Exit the Python interpreter by typing:
python
Copy code
exit()
Once you're back in the shell, you can run the following commands:
bash
Copy code
pip list | grep pyautogen
If pyautogen is listed, then it's installed. If not, you can reinstall it:
bash
Copy code
pip uninstall pyautogen
pip install pyautogen
After reinstalling, you can enter the Python interpreter again by typing python and then try importing pyautogen.
Let's see if this resolves the issue.
User

exit()
root@f1e846ae5f73:~# pip list | grep pyautogen
pyautogen          0.1.8
root@f1e846ae5f73:~# pip uninstall pyautogen
Found existing installation: pyautogen 0.1.8
Uninstalling pyautogen-0.1.8:
Would remove:
/usr/local/lib/python3.10/site-packages/autogen/*
/usr/local/lib/python3.10/site-packages/pyautogen-0.1.8.dist-info/*
Proceed (Y/n)? y
Successfully uninstalled pyautogen-0.1.8
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
root@f1e846ae5f73:~# pip list | grep pyautogen
root@f1e846ae5f73:~# pip install pyautogen
Collecting pyautogen
Obtaining dependency information for pyautogen from https://files.pythonhosted.org/packages/b4/58/bb074fd15c652d4dc7084d9b1f812a00ac9f32feaf4e8ff02686ad340d95/pyautogen-0.1.8-py3-none-any.whl.metadata
Downloading pyautogen-0.1.8-py3-none-any.whl.metadata (13 kB)
Requirement already satisfied: diskcache in /usr/local/lib/python3.10/site-packages (from pyautogen) (5.6.3)
Requirement already satisfied: flaml in /usr/local/lib/python3.10/site-packages (from pyautogen) (2.1.1)
Requirement already satisfied: openai in /usr/local/lib/python3.10/site-packages (from pyautogen) (0.28.1)
Requirement already satisfied: python-dotenv in /usr/local/lib/python3.10/site-packages (from pyautogen) (1.0.0)
Requirement already satisfied: termcolor in /usr/local/lib/python3.10/site-packages (from pyautogen) (2.3.0)
Requirement already satisfied: NumPy>=1.17.0rc1 in /usr/local/lib/python3.10/site-packages (from flaml->pyautogen) (1.26.0)
Requirement already satisfied: requests>=2.20 in /usr/local/lib/python3.10/site-packages (from openai->pyautogen) (2.31.0)
Requirement already satisfied: tqdm in /usr/local/lib/python3.10/site-packages (from openai->pyautogen) (4.66.1)
Requirement already satisfied: aiohttp in /usr/local/lib/python3.10/site-packages (from openai->pyautogen) (3.8.6)
Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/site-packages (from requests>=2.20->openai->pyautogen) (3.3.0)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/site-packages (from requests>=2.20->openai->pyautogen) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/site-packages (from requests>=2.20->openai->pyautogen) (2.0.6)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/site-packages (from requests>=2.20->openai->pyautogen) (2023.7.22)
Requirement already satisfied: attrs>=17.3.0 in /usr/local/lib/python3.10/site-packages (from aiohttp->openai->pyautogen) (23.1.0)
Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib/python3.10/site-packages (from aiohttp->openai->pyautogen) (6.0.4)
Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /usr/local/lib/python3.10/site-packages (from aiohttp->openai->pyautogen) (4.0.3)
Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib/python3.10/site-packages (from aiohttp->openai->pyautogen) (1.9.2)
Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib/python3.10/site-packages (from aiohttp->openai->pyautogen) (1.4.0)
Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.10/site-packages (from aiohttp->openai->pyautogen) (1.3.1)
Using cached pyautogen-0.1.8-py3-none-any.whl (71 kB)
Installing collected packages: pyautogen
Successfully installed pyautogen-0.1.8
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
ChatGPT
Great, you've successfully reinstalled pyautogen.

Now, let's verify that you can import it in Python:
Enter the Python interpreter by typing:
bash
Copy code
python
Once inside the Python interpreter, try importing pyautogen:
python
Copy code
import pyautogen
If there are no errors, then the module has been successfully imported. If you still encounter issues, there might be a problem with the pyautogen package itself or its compatibility with your Python version.
User
root@f1e846ae5f73:~# python
Python 3.10.13 (main, Sep 20 2023, 11:11:20) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

import pyautogen
Traceback (most recent call last):
File "", line 1, in
ModuleNotFoundError: No module named 'pyautogen'
ChatGPT
It's quite unusual that the package is installed but not available for import. Let's try a few things to diagnose and potentially resolve the issue:

Check the Installation Path:
Exit the Python interpreter with exit() and then run:
bash
Copy code
pip show pyautogen
This will give you details about the installed package, including its location. Ensure that the location is indeed in the Python's sys.path.
Try Using Python's -m Flag:
Sometimes, you can use Python's -m flag to run modules even if they aren't directly importable. Try:
bash
Copy code
python -m pyautogen
If this works, it means the module is there but might not be set up for direct importing in the way you expect.
Virtual Environment:
The warning about running pip as the 'root' user suggests using a virtual environment. While this is generally good advice, it might not be the direct cause of your issue. However, if other solutions don't work, setting up a virtual environment and installing the package there can help isolate any potential system-wide conflicts or issues.
Reinstall Python:
As a last resort, there might be an issue with your Python installation itself. Reinstalling Python and then reinstalling the necessary packages might help.
Package Issue:
It's also possible that there's an issue with the pyautogen package itself, especially if it's a less common or less well-maintained package. You might want to check the package's documentation or repository for any known issues or special installation instructions.
Let's start with the first two steps and see if they provide any insights.
User
root@f1e846ae5f73:~# pip show pyautogen
Name: pyautogen
Version: 0.1.8
Summary: Enabling Next-Gen LLM Applications via Multi-Agent Conversation Framework
Home-page: https://github.com/microsoft/autogen
Author: AutoGen
Author-email: auto-gen@outlook.com
License: UNKNOWN
Location: /usr/local/lib/python3.10/site-packages
Requires: diskcache, flaml, openai, python-dotenv, termcolor
Required-by:
ChatGPT
The package pyautogen is indeed installed in /usr/local/lib/python3.10/site-packages, which is a standard location for Python packages and is included in the sys.path you provided earlier.
Given this, the package should be importable. The fact that it's not suggests a couple of possibilities:
Package Structure: The package might not have an init.py file or might be structured in a way that doesn't make its main module directly importable. This is something the package maintainers would need to address.
Corrupted Installation: Sometimes, a package might not install correctly, leading to issues like this. You've already tried reinstalling the package, but it might be worth trying again, perhaps with a different version if one is available.
Python Interpreter: Ensure that the Python interpreter you're using to try the import is the same one that the package was installed for. This seems to be the case given your earlier outputs, but it's always worth double-checking.
Let's try the second diagnostic step I mentioned earlier:
bash
Copy code
python -m pyautogen
If this works, it indicates that the module is present but might not be structured for direct importing. If it doesn't work, it provides further evidence that there's something amiss with the package installation or structure.
User
root@f1e846ae5f73:~# python -m pyautogen
/usr/local/bin/python: No module named pyautogen
root@f1e846ae5f73:~#
ChatGPT
Thank you for trying that out. The error confirms that Python cannot find a module named pyautogen even though pip indicates it's installed.
Given the information, I suspect the issue might be with the package's structure. Let's inspect the contents of the installed package to see if there's an obvious reason it's not being recognized:
Navigate to the package's directory:
bash
Copy code
cd /usr/local/lib/python3.10/site-packages/pyautogen
List the contents of the directory:
bash
Copy code
ls -al
This will give us an idea of the structure of the package and might provide clues as to why it's not being recognized by Python.
User
root@f1e846ae5f73:~# cd /usr/local/lib/python3.10/site-packages/pyautogen
bash: cd: /usr/local/lib/python3.10/site-packages/pyautogen: No such file or directory
root@f1e846ae5f73:~#
ChatGPT
I apologize for the oversight. It seems the package might not have been installed in the expected directory structure.
Let's try a different approach to inspect the package:
Navigate to the site-packages directory:
bash
Copy code
cd /usr/local/lib/python3.10/site-packages/
Search for any directories or files related to pyautogen:
bash
Copy code
ls -al | grep pyautogen
This will help us identify if there's any directory or file related to pyautogen in the site-packages directory.
User
root@f1e846ae5f73:~# cd /usr/local/lib/python3.10/site-packages/
root@f1e846ae5f73:/usr/local/lib/python3.10/site-packages# ls -al | grep pyautogen
drwxr-xr-x  2 root root 4096 Oct  9 01:57 pyautogen-0.1.8.dist-info
ChatGPT
1 / 2
Thank you for the output. It seems that there's a directory pyautogen-0.1.8.dist-info which contains metadata about the pyautogen package, but the actual package content seems to be missing.
Let's inspect the contents of the pyautogen-0.1.8.dist-info directory to see if there's any useful information:
bash
Copy code
ls -al pyautogen-0.1.8.dist-info/
This will list the files inside the pyautogen-0.1.8.dist-info directory. We're particularly interested in any .top_level.txt file, which would indicate the top-level module or package name, or any other files that might give us a hint about the package structure.
User
root@f1e846ae5f73:/usr/local/lib/python3.10/site-packages# ls -al pyautogen-0.1.8.dist-info/
total 68
drwxr-xr-x 2 root root  4096 Oct  9 01:57 .
drwxr-xr-x 1 root root  4096 Oct  9 01:57 ..
-rw-r--r-- 1 root root     4 Oct  9 01:57 INSTALLER
-rw-r--r-- 1 root root 18650 Oct  9 01:57 LICENSE
-rw-r--r-- 1 root root  1141 Oct  9 01:57 LICENSE-CODE
-rw-r--r-- 1 root root 13064 Oct  9 01:57 METADATA
-rw-r--r-- 1 root root  3526 Oct  9 01:57 RECORD
-rw-r--r-- 1 root root     0 Oct  9 01:57 REQUESTED
-rw-r--r-- 1 root root    92 Oct  9 01:57 WHEEL
-rw-r--r-- 1 root root     8 Oct  9 01:57 top_level.txt
root@f1e846ae5f73:/usr/local/lib/python3.10/site-packages#
ChatGPT
Thank you for the output. The file top_level.txt should contain the name of the top-level module or package provided by this distribution. Let's inspect its contents to see what it says:
bash
Copy code
cat pyautogen-0.1.8.dist-info/top_level.txt
This will display the contents of the top_level.txt file, which should give us the name of the top-level module or package.
User
root@f1e846ae5f73:/usr/local/lib/python3.10/site-packages# cat pyautogen-0.1.8.dist-info/top_level.txt
autogen
root@f1e846ae5f73:/usr/local/lib/python3.10/site-packages#
ChatGPT
Thank you for the information. The top-level module for the pyautogen package is named autogen.
To use it in Python, you should import autogen:
python
Copy code
import autogen
Try this in your Python interpreter to see if it works.
User
root@f1e846ae5f73:/usr/local/lib/python3.10/site-packages# python
Python 3.10.13 (main, Sep 20 2023, 11:11:20) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

import autogen

ChatGPT
Great! It seems that the import was successful this time. You can now use the functionalities provided by the autogen module in your Python environment. If you need further assistance or have questions about how to use the module, feel free to ask!
User
so the whole issue was it is called autogen NOT pyautogen?
ChatGPT
Yes, that appears to be the case. The package is named pyautogen on the package index (like PyPI), but the actual module you import in Python is named autogen. This kind of discrepancy can sometimes occur with Python packages. It's always a good idea to check the package's documentation or the top_level.txt file within the package's .dist-info directory to determine the correct module name for importing.
User
well thats annoying
ChatGPT
I understand your frustration. Such discrepancies can indeed be confusing and can lead to unnecessary troubleshooting. It's always a good practice for package maintainers to keep the package name and the module name consistent to avoid such confusion. If you ever encounter similar issues in the future, checking the documentation or the top_level.txt file can be a quick way to verify the correct module name.

Sorry about the confusion.

repo: microsoft/autogen


text:
Can AutoGen access publicly available external data and/or locally saved data?

Is it possible to have Autogen agents make use of external data (say, a dataset from Kaggle) and then perform some tasks on it (simple data analysis,etc) ?
Also, can we feed data that we have saved locally (any .csv or .text file) and perform a similar task?

Yes put the data in the work_dir. Eg the work_dir is set to coding in the quick start example https://github.com/microsoft/autogen#multi-agent-conversation-framework

Example: https://github.com/microsoft/autogen/blob/main/notebook/agentchat_groupchat_vis.ipynb

authors: ViperVille007 gagb sonichi


text:
PR creation in Rider 2022.2 causes exception

I used to create successfully PRs with the JB Rider 2022.2.3 and the Azure DevOps Plugin 1.162.0.
All of sudden I'm receiving the following error, when I try to create a PR (clicking on the '+' button on the topl-left side of the 'Git: Pull Requests' window:
2022-10-07 14:40:03,494 [19319091] SEVERE - #c.i.i.p.PluginManager - com/intellij/openapi/vcs/changes/ui/ChangesBrowser java.lang.NoClassDefFoundError: com/intellij/openapi/vcs/changes/ui/ChangesBrowser 	at com.microsoft.alm.plugin.idea.git.ui.pullrequest.CreatePullRequestDialog.createCenterPanel(CreatePullRequestDialog.java:37) 	at com.intellij.openapi.ui.DialogWrapper.init(DialogWrapper.java:1308) 	at com.microsoft.alm.plugin.idea.common.ui.common.BaseDialogImpl.<init>(BaseDialogImpl.java:59) 	at com.microsoft.alm.plugin.idea.common.ui.common.BaseDialogImpl.<init>(BaseDialogImpl.java:40) 	at com.microsoft.alm.plugin.idea.git.ui.pullrequest.CreatePullRequestDialog.<init>(CreatePullRequestDialog.java:28) 	at com.microsoft.alm.plugin.idea.git.ui.pullrequest.CreatePullRequestController.<init>(CreatePullRequestController.java:35) 	at com.microsoft.alm.plugin.idea.git.ui.pullrequest.VcsPullRequestsModel.createNewItem(VcsPullRequestsModel.java:184) 	at com.microsoft.alm.plugin.idea.common.ui.common.tabs.TabControllerImpl.performAction(TabControllerImpl.java:95) 	at com.microsoft.alm.plugin.idea.git.ui.pullrequest.VcsPullRequestsController.performAction(VcsPullRequestsController.java:34) 	at com.microsoft.alm.plugin.idea.common.ui.common.tabs.TabControllerImpl.actionPerformed(TabControllerImpl.java:84) 	at com.microsoft.alm.plugin.idea.common.ui.common.ActionListenerContainer.triggerEvent(ActionListenerContainer.java:15) 	at com.microsoft.alm.plugin.idea.common.ui.common.ActionListenerContainer.triggerEvent(ActionListenerContainer.java:20) 	at com.microsoft.alm.plugin.idea.common.ui.common.tabs.TabFormImpl$1.actionPerformed(TabFormImpl.java:180) 	at com.intellij.openapi.actionSystem.impl.ActionButton.actionPerformed(ActionButton.java:190) 	at com.intellij.openapi.actionSystem.impl.ActionButton.lambda$performAction$0(ActionButton.java:166) 	at com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareWithCallbacks(ActionUtil.java:337) 	at com.intellij.openapi.actionSystem.impl.ActionButton.performAction(ActionButton.java:166) 	at com.intellij.openapi.actionSystem.impl.ActionButton.processMouseEvent(ActionButton.java:465) 	at java.desktop/java.awt.Component.processEvent(Component.java:6413) 	at java.desktop/java.awt.Container.processEvent(Container.java:2266) 	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5022) 	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324) 	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854) 	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948) 	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575) 	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516) 	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310) 	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2802) 	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854) 	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:781) 	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:730) 	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:724) 	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) 	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) 	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97) 	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:754) 	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:752) 	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) 	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) 	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:751) 	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:918) 	at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.java:840) 	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:763) 	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$6(IdeEventQueue.java:450) 	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:791) 	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$7(IdeEventQueue.java:449) 	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:113) 	at com.intellij.ide.IdeEventQueue.performActivity(IdeEventQueue.java:624) 	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:447) 	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:881) 	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:493) 	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207) 	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) 	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) 	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) 	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) 	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92) Caused by: java.lang.ClassNotFoundException: com.intellij.openapi.vcs.changes.ui.ChangesBrowser PluginClassLoader(plugin=PluginDescriptor(name=Azure DevOps, id=com.microsoft.vso.idea, descriptorPath=plugin.xml, path=~\AppData\Roaming\JetBrains\Rider2022.2\plugins\com.microsoft.vso.idea, version=1.162.0, package=null, isBundled=false), packagePrefix=null, instanceId=88, state=active) 	at com.intellij.ide.plugins.cl.PluginClassLoader.loadClass(PluginClassLoader.java:214) 	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) 	... 57 more
I can kind-of circumvent this, if I create the PR from the Browser UI in Azure DevOps, but this can be a temporary solution only...
Please advise if I can somehow aid the investigations in this error.
Many thanks and kind regards.

Duplicate of #491.

authors: ForNeVeR mits-live

repo: microsoft/azure-devops-intellij


text:
[enhancement]: Allow only container jobs for self-hosted agents for increased security.

Describe your feature request here
It seems like the secure way to deploy a self-hosted agent is to loop infinitely through creating Docker containers with --once, in which Docker-in-Docker is then used by the Agent to subsequently create other Docker containers.
What if we'd have an option to allow only container jobs, making it possible to run the agent on the host without --once, and the agent makes sure that only containerized jobs can be executed?
As a person not involved deeply with this project, it seems like just raising an error in https://github.com/microsoft/azure-pipelines-agent/blob/master/src/Agent.Worker/ExecutionContext.cs#L575 could work, but I guess this would require some other workarounds.
Or is there another simple method one can use to deploy an agent that doesn't let a pipeline definition access/modify any files in the host?

Hi @moqmar thanks for your proposal. We are working on higher-prioritized issues at the moment, but we'll get back to this one as soon as possible.

This is still not implemented AFAIK and was acknowledged as a valid feature request, so it is not stale.

authors: aleksandrlevochkin moqmar

repo: microsoft/azure-pipelines-agent


text:
azure-pipelines-extensions: Vulnerability fixes

Fixed latest CG vulnerabilities

[x] run npm audit fix
[ ] To-do : need to test changes

/azp

/azp run

authors: rajnish-byte v-mohithgc

repo: microsoft/azure-pipelines-extensions


text:
Use defined endpoint data sources from tasks

Question
Is there a way to use the defined endpoint data sources in the extension manifest from task's TypeScript code? does the task library support this?
My case is that I need to call the rest service defined in the endpoint from the task. What I've seen so far is that the data sources are mainly used to populate pick lists in the task definition screens.
Since the endpoints of the rest service can be defined in the extension manifest and I can access some of that info from the task (URL, authentication). I was wondering if there is a way to call the external rest service with a simple call in the task lib (I haven't seen anything in the task lib docs). I would be a nice feature if it is not possible now.
Can you confirm if the alternative now is, for example, to build the call to the external rest service in the task and use the node.js request to make the call?
Thanks,
J.

@jsalado Task lib currently doesn't have any such functionality though i agree it will be good to have. Currently the two options are to use Execute Service Endpoint Request rest API or to call the external rest API directly in task as you mentioned.

@omeshp Thank you for your answer. I'll try to do everything in the task code then as you suggest.
Do you think the task lib will support using the endpoint datasource definitions any time soon. How can I open a feature request fo it?
Best,
J.

@omeshp Thanks for your answer.
I'll implement the call in the task code as you say.
Is the enhancement going to be developed any time soon? How can I open a feature request for it?
Best,
J.

@GitHubSriramB Can you add this request to backlog, if not already present?

ANy news on this?

authors: jsalado kiuwan omeshp

repo: microsoft/azure-pipelines-task-lib


text:
Need a simple way of displaying SQL Print/RaiseError statements in the DevOps release Pipeline log

I have the same need as #9500 allegedly resolved in PR #9741
I'm not convinced this is resolved. I have tried a simple PRINT 'Hello World'; both inline and in a file and the only way of getting "Hello World" to appear in the release log is to set system.debug to "True" and as stated this is not a real option. Far too much noise.
Adding -Verbose appears to do nothing as well.
Below is the yaml
steps:
- task: SqlDacpacDeploymentOnMachineGroup@0
  displayName: 'Deploy using : !Config_ExecuteScriptByDevOps.sql'
  inputs:
    TaskType: sqlQuery
    SqlFile: '$(System.DefaultWorkingDirectory)\OOTB.Config.Database\Deploy\Publish\!Config_ExecuteScriptByDevOps.sql'
    ServerName: '$(SqlServer)'
    DatabaseName: '$(ConfigDatabaseName)'
    AuthScheme: sqlServerAuthentication
    SqlUsername: '$(SqlUserName)'
    SqlPassword: '$(SqlUserPassword)'
    AdditionalArgumentsSql: '-Verbose'

If there is anything I can check, change or confirm; I'm love to know.
Thanks.

Given fix is in other task SqlAzureDacpacDeployment@1 and task which you are using is different SqlDacpacDeploymentOnMachineGroup@0. we are tracking this issue with https://github.com/microsoft/azure-pipelines-tasks/issues/14043. Closing it since its duplicate

authors: AmrutaKawade BlakesHeaven

repo: microsoft/azure-pipelines-tasks


text:
Fix parsing commonName containing slashes

I've encountered errors when trying to build an iOS app in AppCenter, when using a certificate containing a slash in commonName (example: subject=/UID=XXXXXXXXXX/CN=iPhone Distribution: Some Danish Company A/S (YYYYYYYYYY)/OU=YYYYYYYYYY/O=Some Danish Company A/S/C=US.
This happens because of incorrect parsing of openssl command output (value.match(/\/CN=([^/]+)/);) that does not expect slashes in the name.
This commit adds -nameopt multiline option to openssl, so that it splits subject into multiple lines, making it possible to distinguish slashes that are part of the name from path separators.

 Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.:x: ipoddubny sign nowYou have signed the CLA already but the status is still pending? Let us recheck it.

authors: ipoddubny msftclas


text:
Profiler Extension not working on Azure Synapse / Azure Data Warehouse

Azure Data Studio Version:

Steps to Reproduce:
1.Install Azure Data Studio
2.Install SQL Admin extension with SQL Profiler
3.Connect to Azure Data warehouse
4. Error Message appears as Failed to create session: An exception occurred while executing a Transact-SQL statement or batch.

I didn't think synapse supported extended events. Has that changed?

authors: anbudhanush shueybubbles

repo: microsoft/azuredatastudio


text:
Fix model view controls accessibility issues

SQL Operations Studio Version:

Steps to Reproduce:

Closing older unfunded task work-items.

authors: kburtram llali


text:
Can't enter a .bak file name when doing a backup.

Issue Type: Bug
Steps to reproduce:

Right click a DB in the server explorer pane and choose backup
By default the backup name is generated as the DB name followed by -- and the current date and time. Similarly in the backup files list a absolutely path has been added in the default backup location using the backup name as the backup file name.
Click the [-] button to remove the backup file that was auto added to the list.
Click the [+] button to add a backup file - BUG! You are forced to choose a file, but if this is the first time you've backed up this database there is not existing file to pick. The only choices available to you are to select a folder!

Not sure how something this trivial was missed during initial implementation of ADS.
Azure Data Studio version: azuredatastudio 1.10.0 (5fdb967ffcea41df0335ec17cfa396a694bb174e, 2019-08-14T18:28:10.311Z)
OS version: Windows_NT x64 10.0.18362

System Info

Item
Value

CPUs
Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (12 x 3192)

GPU Status
2d_canvas: enabledflash_3d: enabledflash_stage3d: enabledflash_stage3d_baseline: enabledgpu_compositing: enabledmultiple_raster_threads: enabled_onnative_gpu_memory_buffers: disabled_softwareoop_rasterization: disabled_offprotected_video_decode: unavailable_offrasterization: enabledskia_deferred_display_list: disabled_offskia_renderer: disabled_offsurface_synchronization: enabled_onvideo_decode: enabledviz_display_compositor: disabled_offwebgl: enabledwebgl2: enabled

Load (avg)
undefined

Memory (System)
15.81GB (3.39GB free)

Process Argv

Screen Reader
no

VM
0%

Extensions (6)

Extension
Author (truncated)
Version

ssmskeymap
kev
1.1.0

admin-pack
Mic
0.0.2

agent
Mic
0.41.0

import
Mic
0.9.0

profiler
Mic
0.9.0

server-report
Mic
0.1.5

@peterlukerow Hi there - I was re-testing this in ADS 1.34 and have confirmed that you can now remove the default entry provided for a backup file name, and then manually type in a filename for the new backup.  Can you please confirm you now see this same behavior?  Thank you!

@erinstellato-ms I do see the same behavior, maybe it was like this all along.
The UI is a little misleading in that you click button to add file and you get a tree view. Like I said if you have never backed up the database in question there is no existing file. Under the tree view is a textbox labelled "selected path", which implies this is the folder to put the file in. It seems like there should be a separate textbox for the filename or "Selected path" is changed to "Filename".

@peterlukerow Thanks for taking the time to explain the issue, I didn't understand it initially, but I was able to step through and I think I see the challenge.
For my own reference in the future:

Create a new database.
Backup the database in ADS.
Remove the default backup file (via the - icon).
Use the + icon to add a new file.
The Selected path dialog defaults to the default backup folder for the instance, but the filename is not populated.
Further, if you select discard and then Cancel out of the backup window, and then try to backup the database again, the defaults are populated again for the path and filename, but the remove button ( - icon) is grayed out, and you cannot change the path or file name.  (If you add another filename, then the remove button becomes accessible.)
Lastly, if you cancel out of the backup dialog and then try to drop the database, you cannot.  A shared database lock exists for the database (can be seen by running DROP DATABASE and then querying sys.dm_exec_requests while it's trying to complete)

authors: erinstellato-ms peterlukerow


text:
Additional tests for the import wizard

Coverage increased (+0.5%) to 36.789% when pulling 1872eb5d873b8fdfad841fdf3b9d8492d5726f4b on aasim/import/testing into a69032e3172608e17984507b40d2bb9c8c509750 on main.


text:
Add rollup dependency

Replacing the other PR - just adding back in the rollup module that was removed during the VS Code merge to fix the compile error when building the build folder in dev.

Pull Request Test Coverage Report for Build 808364902

0 of 0   changed or added relevant lines in 0 files are covered.
No unchanged relevant lines lost coverage.
Overall coverage remained the same at 43.538%

Totals

Change from base Build 807744838:
0.0%

Covered Lines:
26464

Relevant Lines:
55320

💛  - Coveralls

authors: Charles-Gagnon coveralls


text:
Skip manage packages test

Skipping the manage packages test for now.
The test is unstable because of the way that the wizard is initialized. While debugging I realized the wizard contents get reset twice. This isn't an issue for users since it happens really quickly (before the user can type anything). But it makes the smoke test unstable since sometimes, 'pyarrow' gets typed and then cleared by the reset. I need to do some refactoring for how the wizard initialization.

Pull Request Test Coverage Report for Build 2310242135

0 of 0   changed or added relevant lines in 0 files are covered.
No unchanged relevant lines lost coverage.
Overall coverage remained the same at 42.065%

Totals

Change from base Build 2309651695:
0.0%

Covered Lines:
27927

Relevant Lines:
62082

💛  - Coveralls


text:
New extension for migrating data from Oracle to Azure SQL

Extension 'Data Migration for Oracle' for migrating data from Oracle source to Azure SQL.

Oops, looks like a license file was deleted recently. I went ahead and updated it here even though it's unrelated to your extension just to simplify the update...

authors: Charles-Gagnon neetusingh-ms


text:
DialogClass and Class memory scopes don't evaluate expressions

Version
4.8 nighlties
Describe the bug
When we added dialogclass and class scopes we didn't have expression properties.  Now that we have formalized expression properties, we don't have a way from the memory scope to do the evaluation of the expressions to get the actual configuration.
Expected behavior
If I have a class with an expressionProperty on it, the memory scope shows the evaluated value for the property.
{
BoolExpression IsVip {get;set;}
}
The memory scope for this should be able to be "class.IsVip" to get the actual value of IsVIP
[bug]

merged

authors: Kaiqb tomlm

repo: microsoft/botbuilder-dotnet


text:
Azure-devops readme - Missing step to install Azure devops extension to az cli for the current steps to work

In addition to installing Azure CLI, the Azure devops extension should be installed for the "az devops" command in the readme to work.

The below link can be used in the readme for how to install the devops extension.
https://marketplace.visualstudio.com/items?itemName=ms-vsts.cli

The command that is in the readme currently is "az devops project create -n $PROJECT_NAME".

This command is incorrect and has to be like the below instead.
"az devops project create --name $PROJECT_NAME --organization $ORG_NAME"
where PROJECT_NAME --> name to give to your project
ORG_NAME --> URI of your devops organization eg. http://dev.azure.com/epicstuff

We believe this to be well documented now.

authors: jananivMS nmiodice

repo: microsoft/cobalt