Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
154798 stories
·
33 followers

New Desalination System Turns Seawater Into Drinking Water and Useful Salts - Including Lithium

1 Share
"Scientists have developed a solar desalination system that turns seawater into drinking water without creating environmentally damaging brine," reports ScienceDaily. "Special laser-textured metal panels use sunlight to evaporate water while automatically moving salt deposits away from the working surface, preventing clogging. The process was successfully tested with water from three oceans and can recover nearly all salts as solids. Those leftover materials could even become a source of valuable lithium for batteries." (The research team was led by University of Rochest professor Chunlei Guo and published their results in the journal Light: Science & Applications.) The University of Rochester has made an announcement: The technology uses solar panels made of black metal etched with femtosecond lasers to make the surface super light-absorbing and superwicking — or extremely attractive to water. The panels have a laser-treated active region that pulls a thin layer of water across the surface, absorbs nearly all solar radiation, distills the water, and deposits the leftover salts and minerals into the panel's untreated sides or "passive" region so that the salt does not clog the active region and disrupt continuous desalination... Guo's team precisely etched the black metal's grooves so the various salts and minerals in ocean water would simply slough off... [I]t extracts nearly 100 percent of the salts in solid form. This could not only produce an abundant supply of table salt, but it could also be used to extract more precious minerals, including lithium, which is used in the lithium-ion batteries that power electric vehicles and other electronics. In a related paper in the Journal of Materials Chemistry A, Guo and his colleagues show how they can use the same superwicking solar panels to separate lithium from the rest of other salts in desalination. Embedding nanoparticles made of hydrogen titanate in the tiny grooves of the black metal surface isolates the lithium from other salts and minerals...Using water samples from Great Salt Lake, the researchers extracted about 50 percent of the lithium from the salts left behind by the desalination process. Guo says now that the superwicking desalination technology has been demonstrated in proofs of concept on small-scale devices, he sees the technology inherently scalable, capable of improving global access to drinking water and building more sustainable supply chains for precious minerals. "The National Science Foundation, the Bill & Melinda Gates Foundation, and Worldwide Universities Network supported this research."

Read more of this story at Slashdot.

Read the whole story
alvinashcraft
17 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

How To Fix Common TypeScript Issues With Qodana

1 Share
How to fix common TypeScript issues with Qodana

Most TypeScript projects already run ESLint with @typescript-eslint. That covers a lot: explicit any, floating promises, non-null assertions, and more. If your linting setup is solid, you’re catching the obvious issues in the editor before code review.

ESLint rules can’t produce cross-file findings. Each rule runs within a single file’s scope, which means ESLint can’t tell you that an export is unused everywhere in the codebase, that an any-typed value from one file is causing unsafe assumptions five files away, or that two components implement the same logic independently. That’s the gap Qodana fills.

Here are five TypeScript issues worth addressing, organized by what ESLint handles and where it runs out of scope.

Implicit any spreading through your codebase

ESLint’s no-explicit-any catches places where you write any. It doesn’t track what happens when any enters your codebase from external sources, such as from response.json(), a third-party library without types, or an untyped import. Once an externally-typed any value enters your code, it propagates silently through property accesses and function calls. ESLint’s no-unsafe-* rules can catch this, but only if you’re using @typescript-eslint/recommended-type-checked, which requires type-aware linting and is significantly less common than the standard recommended config.

async function getUser(id: string) {
  const res = await fetch(`/api/users/${id}`);
  const data = await res.json(); // type: any

  return data.profile.name; // no error — crashes if profile is undefined
}

response.json() returns any in the standard lib. Everything downstream is untyped. The compiler accepts any property name and any method call. The bug surfaces at runtime. Qodana tracks how any flows through the program across files. When an any-typed value reaches a code path where a specific shape is assumed, it flags the discrepancy, even if that’s several function calls away from where any entered the codebase.

Adding UserResponse doesn’t fix this. It just moves the lie closer to the crash. Type the boundary instead:

interface UserResponse {
  profile: { name: string };
}

const data: UserResponse = await res.json();

If the API response shape changes, the type error surfaces at compile time.

Non-null assertions used as shortcuts

ESLint’s no-non-null-assertion flags every ! operator uniformly. That works, but many teams disable the rule or add broad exceptions because legitimate uses, like after a runtime check, get flagged alongside the dangerous ones. The signal gets noisy, the rule gets turned off, and the problem disappears from view.

function renderUser(user: User | null) {
  return `Hello, ${user!.name}`; // crashes at runtime if user is null
}

const button = document.querySelector(".submit-btn");
button!.addEventListener("click", handleSubmit); // crashes if element doesn't exist

Both examples compile without errors. Both crash under predictable conditions. The ! is often added to silence a type error without fixing the underlying issue.

The correct approach is to handle the null case:

function renderUser(user: User | null) {
  if (!user) return "Guest";
  return `Hello, ${user.name}`;
}

const button = document.querySelector(".submit-btn");
if (button) {
  button.addEventListener("click", handleSubmit);
}

Qodana surfaces non-null assertions as a separate category in the report. Not every ! is wrong, but seeing them gathered in one place makes it easier to distinguish the legitimate uses from the shortcuts, without having to choose between a noisy rule and no rule at all.

Floating promises

ESLint’s @typescript-eslint/no-floating-promises is effective, but it’s a type-aware rule. It requires TypeScript type checking to be enabled in your ESLint config via parserOptions.project. In projects where that’s not configured, or configured only for part of the codebase, the rule silently doesn’t run on uncovered files.

async function onSubmit(data: FormData) {
  saveToDatabase(data); // Promise<void>, not awaited
  router.push("/success"); // runs before save completes
}

TypeScript accepts this without complaint. Calling an async function without await is considered valid syntax, and the return value is discarded. However, this behavior is incorrect: The user sees the success page before the save completes, and any database error is silently swallowed.

async function onSubmit(data: FormData) {
  await saveToDatabase(data);
  router.push("/success");
}

Qodana’s analysis is type-aware by default across the whole project, without requiring ESLint’s TypeScript integration to be separately configured. Floating promises get flagged consistently regardless of how the project’s ESLint setup is structured.

Unused exports

noUnusedLocals in tsconfig catches unused variables within a file. Exported symbols are excluded by design. From the compiler’s perspective, something outside the current file might import them. ESLint’s eslint-plugin-import provides an import/no-unused-modules rule that can detect this, but it requires scanning the entire dependency graph on every lint run and carries significant performance overhead on large codebases. For most projects, it’s not practical to keep it enabled.

// utils/format.ts
export function formatCurrency(n: number): string { ... }
export function formatPercent(n: number): string { ... } // removed feature, still here
export function formatBytes(n: number): string { ... }    // never imported anywhere

All three pass without a warning. But formatPercent and formatBytes are dead code. They add maintenance surface, slow down refactors, and mislead developers who assume exported symbols are in use.

Detecting this requires whole-project analysis. Qodana builds a reference graph across the entire codebase and tracks every import and re-export. Symbols that appear only as sources, never as import targets, get flagged. Neither tsc nor ESLint can do this.

Duplicated logic across files

ESLint doesn’t have native duplication detection. Standalone tools like jscpd exist for this, but they’re not part of your linting pipeline. That means separate setup, separate maintenance, and another thing to remember. The result: logic that gets copied between components or utility files accumulates without anyone flagging it.

// components/UserCard.tsx
function formatUserName(user: User): string {
  if (!user.firstName && !user.lastName) return "Anonymous";
  return [user.firstName, user.lastName].filter(Boolean).join(" ");
}
// components/UserBadge.tsx
function getDisplayName(user: User): string {
  if (!user.firstName && !user.lastName) return "Anonymous";
  return [user.firstName, user.lastName].filter(Boolean).join(" ");
}

This isn’t a style issue. It means bug fixes need to be applied in multiple places, and when they aren’t, behavior diverges silently between the two copies.

Qodana detects duplicated code across files as part of the same analysis pass that surfaces type issues and unused exports. When it appears in the report alongside everything else, it’s harder to deprioritize than a separate tool nobody remembers to run.

Setting up Qodana for your TypeScript project

All five issues above are visible in Qodana’s default profile for JavaScript and TypeScript projects. Here is a minimal qodana.yaml to get you started:

  version: "1.0"
  linter: jetbrains/qodana-js:2026.1                                                                                                                                                                                                             
  bootstrap: npm ci                                                                                                                                                                                                                              
  profile:                                                                                                                                                                                                                                       
    name: qodana.recommended                                                                                                                                                                                                                     
  failThreshold: 0                                                                                                                                                                                                                               
  exclude:        
    - name: All                                                                                                                                                                                                                                  
      paths:
        - dist                                                                                                                                                                                                                                   
        - node_modules

If the first run surfaces hundreds of existing issues, don’t let that block CI adoption. Qodana’s baseline feature captures the current state of the project in a qodana.sarif.json file. Commit it, and from that point on, CI only fails on newly introduced problems. The existing backlog stays visible in the report, but it doesn’t block every PR while you work through it.

Fix common TypeScript issues

Ready to fix common TypeScript issues with Qodana?

Try Qodana and let us know what you think.

Try Qodana Ultimate Plus

We’d like to extend a special thank-you to Qodana developer Lev Liadov for his contribution to this guide.

Read the whole story
alvinashcraft
17 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Judging beautiful docs, AI fatigue, and tool slop

1 Share
In this podcast, I chat with Fabrizio Ferri-Benedetti about what makes documentation beautiful — drawing on Italo Calvino's literary principles of lightness and quickness — the reality of AI review fatigue versus creator fatigue, why most vibe-coded tools are actually 'tool slop,' developing internal skills for repeatable doc processes, and the emerging future of running local AI models.

Read the whole story
alvinashcraft
18 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

How to use Visual Studio Profiler and GitHub Copilot

1 Share
From: Daniel Hindrikes
Duration: 4:55
Views: 4

In this video, I will show you how GitHub Copilot can use Visual Studio Profiler to make your code better.

Read the whole story
alvinashcraft
18 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

131. Fluent UI Blazor in the Microsoft Ecosystem: Open Source, Aspire and Beyond - with Vincent Baaij

1 Share

In this episode, Rick & Oscar talk with Vincent Baaij, solution architect at Rubicon and principal maintainer of Microsoft’s Fluent UI Blazor library. Vincent shares how a small open-source contribution grew into a leading role within the Fluent UI Blazor ecosystem, while discussing the challenges of open-source maintenance, accessibility, and AI-driven development. The conversation highlights how human expertise and collaboration remain essential as software development continues to evolve.

About this episode, and Vincent Baaij in particular: you can find Vincent on LinkedIn or visite his website. Here you can find the Fluid UI Blazor website and the GitHub repository.

About Betatalks: watch our videos and follow us on Instagram, LinkedIn, and Bluesky





Download audio: https://www.buzzsprout.com/1622272/episodes/19258123-131-fluent-ui-blazor-in-the-microsoft-ecosystem-open-source-aspire-and-beyond-with-vincent-baaij.mp3
Read the whole story
alvinashcraft
18 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

J. Tower: A.I. Workflows - Episode 404

1 Share

https://clearmeasure.com/developers/forums/

Jonathan Tower — known to friends and colleagues simply as "J." — is the founding partner of Trailhead Technology Partners, a custom software consulting firm with employees across the U.S., Europe, and South America. A 12-time Microsoft MVP for .NET and a Telerik Developer Expert, J. brings nearly 25 years of industry experience spanning roles from senior architect to director of development. He was recently elected to the .NET Foundation Board of Directors for the 2026–2027 term and is the driving force behind Beer City Code, Western Michigan's largest professional software conference. J. is also a LinkedIn Learning course author and an active speaker at software conferences around the world; including being a speaker at the most recent .NET Conf.

LinkedIn - https://www.linkedin.com/in/jtower/
Website - https://www.jtower.com/
Trailhead Technology Website - https://trailheadtechnology.com/
Trailhead Technology Events - https://trailheadtechnology.com/events
Trailhead Technology Blogs - https://trailheadtechnology.com/blog
Beer City Code- https://beercitycode.com/

Previous Appearances on the Azure & DevOps Podcast:

Episode 371 - Software Leadership with Jonathan "J." Tower https://azuredevopspodcast.clear-measure.com/software-leadership-with-jonathan-j-tower-episode-371
Episode 263 - J. Tower: Modernization Strangler Fig Pattern https://azuredevopspodcast.clear-measure.com/j-tower-modernization-strangler-fig-pattern-episode-263

----------------------------------------
Want to Learn More?
Visit AzureDevOps.Show for show notes and additional episodes.





Download audio: https://traffic.libsyn.com/clean/secure/azuredevops/Episode_404.mp3?dest-id=768873
Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories